-{
- "01" : { "uri" : "/images/sponsors/isp42.png",
- "title" : "<span>Hosting</span>-Sponsor",
- "link" : "http://www.isp42.de/" },
- "02" : { "uri" : "/images/sponsors/isp42_2.png",
- "title" : "<span>Hosting</span>-Sponsor",
- "link" : "http://www.isp42.de/" },
- "03" : { "uri" : "/images/cebit2010_logo_en.png",
- "title" : "<span>CeBIT</span> 2010",
- "link" : "cebit" }
-}
+[
+ { "uri" : "images/sponsors/isp42.png",
+ "title" : "<span>Hosting</span>-Sponsor",
+ "link" : "http://www.isp42.de/" },
+ { "uri" : "images/sponsors/isp42_2.png",
+ "title" : "<span>Hosting</span>-Sponsor",
+ "link" : "http://www.isp42.de/" },
+ { "uri" : "images/cebit2010_logo_en.png",
+ "title" : "<span>CeBIT</span> 2010",
+ "link" : "cebit" }
+]
+++ /dev/null
-jquery-ui-1.7.2.custom.min.js
\ No newline at end of file
+++ /dev/null
-(function(a){a.fn.alternate=function(b,c){var d=a.extend({},a.fn.alternate.defaults,b);return this.each(function(e){var f=a(this),g=a.meta?a.extend({},d,f.data()):d;if(e%2==0&&d.even.length){f.removeClass(d.odd).addClass(d.even)}else{if(d.odd.length){f.removeClass(d.even).addClass(d.odd)}}if(c){f.click(c)}if(d.hover){f.bind("mouseenter mouseleave",function(h){a(this).toggleClass("hover")})}})};a.fn.alternate.defaults={odd:"odd",even:"even",hover:false}})(jQuery);
\ No newline at end of file
+++ /dev/null
-jquery-1.3.2.min.js
\ No newline at end of file
+++ /dev/null
-
-(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,cells[i]);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,node){var l=parsers.length;for(var i=1;i<l;i++){if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)){return parsers[i];}}return parsers[0];}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=table.tBodies[0].rows[i],cols=[];cache.row.push($(c));for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));}cols.push(i);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){if(!node)return"";var t="";if(config.textExtraction=="simple"){if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){t=node.childNodes[0].innerHTML;}else{t=node.innerHTML;}}else{if(typeof(config.textExtraction)=="function"){t=config.textExtraction(node);}else{t=$(node).text();}}return t;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){rows.push(r[n[i][checkCell]]);if(!table.config.appender){var o=r[n[i][checkCell]];var l=o.length;for(var j=0;j<l;j++){tableBody[0].appendChild(o[j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false,tableHeadersRows=[];for(var i=0;i<table.tHead.rows.length;i++){tableHeadersRows[i]=0;};$tableHeaders=$("thead th",table);$tableHeaders.each(function(index){this.count=0;this.column=index;this.order=formatSortingOrder(table.config.sortInitialOrder);if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(!this.sortDisabled){$(this).addClass(table.config.cssHeader);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){i=(v.toLowerCase()=="desc")?1:0;}else{i=(v==(0||1))?v:0;}return i;}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(getCachedSortType(table.config.parsers,c)=="text")?((order==0)?"sortText":"sortTextDesc"):((order==0)?"sortNumeric":"sortNumericDesc");var e="e"+i;dynamicExp+="var "+e+" = "+s+"(a["+c+"],b["+c+"]); ";dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function sortText(a,b){return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){var DECIMAL='\\'+config.decimal;var exp='/(^[+]?0('+DECIMAL+'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)'+DECIMAL+'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*'+DECIMAL+'0+$)/';return RegExp(exp).test($.trim(s));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}$("tr:visible",table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
\ No newline at end of file
{
- "name" : "IPFire",
- "sname" : "ipfire",
- "slogan" : "Security now!",
- "releases" : { "stable" : "IPFire 2.5 - Core 34",
- "testing" : "IPFire 3.0 alpha 1" },
- "hosting" : { "cluster" : "minerva.ipfire.org" },
+ "cluster" : { "hostname" : "minerva.ipfire.org" },
"nightly_builds" : [{ "url" : "http://ftp.ipfire.org/pub/nightly-builds/",
"path" : "/srv/anonftp/pub/nightly-builds" },
{ "url" : "http://www.rowie.at/upload/ipfire/builds/" }],
+++ /dev/null
-#!/usr/bin/python
-
-import cgitb
-cgitb.enable()
-
-import sys
-import cgi
-import imputil
-
-site = cgi.FieldStorage().getfirst("site") or "index"
-
-sys.path = [ "pages",] + sys.path
-for s in (site, "static"):
- try:
- found = imputil.imp.find_module(s)
- loaded = imputil.imp.load_module(s, found[0], found[1], found[2])
-
- p = loaded.__dict__["page"]
-
- break
- except ImportError, e:
- pass
-
-p()
-{
- "10" : { "uri" : "/index",
- "name" : "Home" },
- "20" : { "uri" : "/download",
- "name" : "Downloads" },
- "30" : { "uri" : "/screenshots",
- "name" : "Screenshots" },
- "40" : { "uri" : "http://wiki.ipfire.org/",
- "name" : { "de" : "Wiki", "en" : "Wiki" }},
- "50" : { "uri" : "http://forum.ipfire.org/",
- "name" : "Forum" },
- "60" : { "uri" : "/development",
- "name" : { "de" : "Entwicklung", "en" : "Development" }},
- "70" : { "uri" : "/links",
- "name" : "Links" },
- "80" : { "uri" : "/cebit",
- "name" : "<div style=\"color:#f90;\">CeBIT 2010</div>" }
-}
+[
+ { "uri" : "/index",
+ "name" : "Home" },
+ { "uri" : "/download",
+ "name" : "Downloads" },
+ { "uri" : "/screenshots",
+ "name" : "Screenshots" },
+ { "uri" : "http://wiki.ipfire.org/",
+ "name" : { "de" : "Wiki", "en" : "Wiki" }},
+ { "uri" : "http://forum.ipfire.org/",
+ "name" : "Forum" },
+ { "uri" : "/development",
+ "name" : { "de" : "Entwicklung", "en" : "Development" }},
+ { "uri" : "/cebit",
+ "name" : "<div style=\"color:#f90;\">CeBIT 2010</div>" }
+]
--- /dev/null
+[
+ {
+ "name" : "IPFire Project",
+ "location" : {
+ "city" : "Cologne",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "mirror1.ipfire.org",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : true,
+ "pakfire3" : true
+ }
+ },
+
+ {
+ "name" : "Ronald Wiesinger",
+ "location" : {
+ "city" : "Vienna",
+ "country" : "Austria",
+ "country_code" : "at"
+ },
+ "hostname" : "www.rowie.at",
+ "path" : "/ipfire",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : false,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "Jan Paul Tücking",
+ "location" : {
+ "city" : "Karlsruhe",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "ipfire.earl-net.com",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : false,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "Markus Villwock",
+ "location" : {
+ "city" : "Hannover",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "kraefte.net",
+ "path" : "/ipfire",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : true,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "ISP42",
+ "location" : {
+ "city" : "Hannover",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "mirror2.ipfire.org",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : true,
+ "pakfire3" : true
+ }
+ },
+
+ {
+ "name" : "Peter Schälchli",
+ "location" : {
+ "city" : "Paris",
+ "country" : "France",
+ "country_code" : "fr"
+ },
+ "hostname" : "mirror3.ipfire.org",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : true,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "Peter Schälchli",
+ "location" : {
+ "city" : "Cologne",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "mirror5.ipfire.org",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : true,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "Kim Barthel",
+ "location" : {
+ "city" : "Stuttgart",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "ipfire.kbarthel.de",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : false,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "Kim Barthel",
+ "location" : {
+ "city" : "Stuttgart",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "ipfire.1l0v3u.com",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : false,
+ "pakfire3" : false
+ }
+ },
+
+ {
+ "name" : "Sebastian Winter",
+ "location" : {
+ "city" : "Minden",
+ "country" : "Germany",
+ "country_code" : "de"
+ },
+ "hostname" : "ipfiremirror.wintertech.de",
+ "path" : "",
+ "serves" : {
+ "isos" : true,
+ "pakfire2" : false,
+ "pakfire3" : false
+ }
+ }
+]
{ "en" : "<p>The linux user group from Lünen
released an article about ipfire.</p>",
"de" : "<p>Die Linux-User-Group aus Lünen hat einen Artikel
- über IPFire auf ihrer Webseite veröffentlicht.</p>"}},
+ über IPFire auf Ihrer Webseite veröffentlicht.</p>"}},
"05" : {"author" : "Michael Tremer",
"mail" : "michael.tremer@ipfire.org",
"de" : "<p>Heute werden wir <strong>Core 32</strong> veröffentlichen. Es bringt die folgenden Änderungen mit sich:</p>
<ul>
<li>Update von openvpn auf Version 2.1rc20</li>
- <li>Update von setdns.pl nun werden auch regfish.de Account richtig aktuallisiert</li>
+ <li>Update von setdns.pl nun werden auch regfish.de Account richtig aktualisiert</li>
<li>Update von squid auf Version 2.7.STABLE7</li>
<li>Update von ntfs3g, vielleicht behebt dieses ein paar mount Probleme</li>
<li>Update der Hardware Datenbank</li>
target=\"_blank\">dieses Sicherheitsproblem</a> zu blockieren.</li>
<li>Fix von einigen Tippfehler (Device xxx reports S.M.A.R.T. etc.)</li>
<li>Update Net-Server auf Version 0.97</li>
- <li>Pakfire: Aktualisiert nun auch die meta db beim \"package list\" Update.<br />
- Dieses verhindert die Benutzung von alten Abhängigkeiten bei der Paketaktualisierung.</li>
+ <li>Pakfire: AktualiSiert nun auch die meta db beim \"package list\" Update.<br />
+ Dieses verhindert die Benutzung von alten Abhängigkeiten bei der PaketaktualiSierung.</li>
</ul>
<br />"}},
"de" : "<p>Das IPFire Core Development Team ist stolz zwei neue Mitglieder vorzustellen.
<strong>Stefan Schantl</strong> und <strong>Jan Paul Tücking</strong> sind von
+<<<<<<< HEAD:www/news.json
nun an Teil des Teams aufgrund ihrer beständigen und langen Mitarbeit am Projekt.</p>
+=======
+ nun an Teil des Teams aufgrund Ihrer beständigen und langen Mitarbeit am Projekt.</p>
+>>>>>>> next:www/news.json
<p>
<a href=\"http://wiki.ipfire.org/de/project/contribute\" target=\"_blank\">Wie kann ich selber zum Projekt beitragen?</a>
</p>"}},
"de" : "<p>Marcus Scholz hat einen <a href=\"http://www.commander1024.de/wordpress/2009/12/ipfire-talk-in-der-warpzone/\" target=\"_blank\">Vortrag</a> über
IPFire in der <a href=\"http://warpzone.ms/\" target=\"_blank\">Warpzone</a> gehalten. Die dazugehörigen
<a href=\"http://www.commander1024.de/wordpress/wp-content/uploads/2009/12/IPFire-Talk.pdf\" target=\"_blank\">Folien</a>
+<<<<<<< HEAD:www/news.json
so wie ein <a href=\"http://qik.com/video/3807703\" target=\"_blank\">Video</a> von seiner Presentation stehen zur Verfügung.
+=======
+ so wie ein <a href=\"http://qik.com/video/3807703\" target=\"_blank\">Video</a> von seiner Präsentation stehen zur Verfügung.
+>>>>>>> next:www/news.json
</p>"}},
"25" : {"author" : "Michael Tremer",
</p>",
"de" : "<p>Heute werden wir das erste Update im Jahr 2010 veröffentlichen.
- Das <strong>Core 34</strong> Update kommt mit folgenden Änderungen:</p>
+ Das <strong>Core 34</strong> Update weist folgende Änderungen auf:</p>
<p>
<ul>
<li><strong>Kernel Update auf 2.6.27.42</strong></li>
<li>Update von alsa auf 1.0.22(.1)</li>
<li>Update von v4l-dvb</li>
<li>Update von compat-wireless auf 2.6.32.2</li>
- <li>Standardtreiber von atheros auf ath5k getauscht</li>
- <li>kvm-kmod hinzugefügt um die kvm api für qemu zu aktualliesieren</li>
- <li>Atheros/Attansic atl1c Netzwerktreiber hinzugefügt</li>
- <li>Patches für die Erkennung von Realtek 8102/8103 zu r8101 Treibern hinzugefügt</li>
- <li>Patch für die Wake-on-Lan Probleme des Intel E100 zu beheben hinzugefügt</li>
+ <li>Wechsel des Standardtreibers von atheros auf ath5k</li>
+ <li>Ergänzung von kvm-kmod zwecks AktualiSierung der kvm api für qemu</li>
+ <li>Erweiterung um Atheros/Attansic atl1c Netzwerktreiber</li>
+ <li>Ergänzung um Patches für die Erkennung von Realtek 8102/8103 zu r8101 Treibern</li>
+ <li>Behebung der Wake-on-Lan Probleme der Intel E100 NIC durch das Hinzufügen eines Patches</li>
</ul>
</ul>
<ul>
- <li>usb_modeswitch 1.0.6 hinzugefügt</li>
- <li>compile-Option für die DCF77-clocks hinzugefügt</li>
+ <li>Erweiterung um usb_modeswitch 1.0.6</li>
+ <li>NTP: Unterstützung für DCF77-Uhren</li>
<li>Update von smartmontools auf 5.39 stable</li>
- <li>Sicherstellung, dass das ehci_hci Modul zu erst geladen wird (behebt USB2.0-Erkennung)</li>
+ <li>Sicherstellung, dass das ehci_hci Modul zuerst geladen wird (behebt USB2.0-Erkennung)</li>
</ul>
<ul>
- <li>IPSEC:</li>
+ <li>IPSEC-Verbesserungen:</li>
<ul>
- <li>Nun sind IPSec Peers auch durch IPFire erreichbar</li>
- <li>Nicht funktionerende Crytomodule wurden aus der IPSec-Konfiguration gelöscht</li>
+ <li>IPSec Peers sind nun ebenfalls durch IPFire erreichbar</li>
+ <li>Nicht funktionierende Cryptomodule wurden aus der IPSec-Konfiguration gelöscht.</li>
</ul>
<li>IPTV Verbesserungen:</li>
<ul>
<li>Update von dhcpcd</li>
<li>Fix für den iqmpproxy Installationscheck (pppsetup.cgi)</li>
- <li>Verbesserung an der mac.cgi Seite, Änderungen am Tabellenlayout und Beschreibungen hinzugefügt.</li>
+ <li>Verbesserung an der mac.cgi Seite, Änderungen am Tabellenlayout und Ergänzungen von Beschreibungen.</li>
</ul>
- <li>CGI Änderugen:</li>
+ <li>CGI Änderungen:</li>
<ul>
- <li>Spendenbutton auf der Credits Seite hinzugefügt</li>
- <li>Es wurde ein Patch hinzugefügt um das oinkmaster Verzeichniss tmp auf /var/tmp zu ändern</li>
- <li>\"time constraints feature\" und \"local port adressing\" zur ausgehenden Firewall hinzugefügt</li>
+ <li>Hinzufügen eines Spendenbuttons auf der Credits Seite</li>
+ <li>Erweiterung um ein Patch, zwecks Änderung des oinkmaster Verzeichnisses tmp auf /var/tmp</li>
+ <li>Erweiterung um ein \"time constraints feature\" und \"local port adressing\" zur ausgehenden Firewall</li>
<li>Neugestaltung der chpasswd.cgi</li>
<li>Verbesserung der Pakfire \"Ping\" Beschreibung auf der pakfire.cgi</li>
- <li>ExtraHD-Seite ist nun mehrsprachig</li>
- <li>Behoben, dass crontab beim ramdisk restore ersetzt wurde</li>
+ <li>Erweiterung auf eine mehrsprachige ExtraHD-Seite</li>
+ <li>Beseitigung des Fehlers, dass beim RAM-Disk Restore Crontab ersetzt wurde</li>
</ul>
<li>Installer:</li>
<ul>
- <li>Installer device von /dev/tty1 nach /dev/console geändert</li>
+ <li>Änderung des Installer device von /dev/tty1 nach /dev/console geändert</li>
<li>Update von memtest86+ auf 4.00</li>
</ul>
<li>Sprachen:</li>
<ul>
- <li>Die Unterstützung von französisch dem Installer hinzugefügt</li>
+ <li>Unterstützung der französischen Sprache beim Installer</li>
</ul>
</ul>
</p>
<p>
- Durch den <strong>Kernelupdate</strong> ist ein <strong>Neustart</strong> von IPFire nötig! <br/>
- <strong>Achtung</strong>: Grub wird neu installiert, wenn die Konfiguration manuell geändert
+ Durch das <strong>Update</strong> des <strong>Kernels</strong> ist ein <strong>Neustart</strong>
+ von IPFire nötig! <br/>
+ <strong>Achtung</strong>: Grub wird neu installiert. Wenn die Konfiguration manuell geändert
wurde muss diese zuerst wieder hergestellt werden!<br />
- <strong>Xen</strong> User müssen vor dem Neustart der Machine auch linux-xen updaten!
- </p>"}}
+ <strong>Xen</strong> User müssen vor dem Neustart der Maschine zuerst linux-xen updaten,
+ da es sonst zu Fehlern kommt!
+ </p>"}},
+ "27" : {"author" : "Jan Paul Tuecking",
+ "mail" : "earl@ipfire.org",
+ "subject" : { "en" : "Core Update 35", "de" : "Core Update 35" },
+ "date" : "2010-01-28",
+ "link" : "",
+ "content" :
+ { "en" : "<p>Today we are going to release <strong>Core 35</strong>.
+ It implicates following changes:</p>
+ <p>
+ <ul>
+ <li>Applied the latest <strong>security patches</strong> to squidGuard to prevent buffer overflows and
+ from going into emergency mode when overlong URLs are encountered</li>
+ <li>Add missing modules for intersil/prism (disabled) </li>
+ <li>Disabled connscheduler on general (*)</li>
+ <li>Add zerofree to cleanup flash and xenimages (*)</li>
+ <li>Fix for countrycode list (thx to m.a.d)</li>
+ </ul>
+ <ul>
+ <li>Webinterface:</li>
+ <ul>
+ <li>Fix the link to external Snort SID page</li>
+ </ul>
+ <li>Outgoing Firewall:</li>
+ <ul>
+ <li>Parse pre Core34 rules correct and enabled change logging in mode 1</li>
+ <li>Added GRE and ESP protocol to outgoing firewall</li>
+ </ul>
+ <li>Xen:</li>
+ <ul>
+ <li>Fix klogd fails on xen-kernel</li>
+ <li>Disabled start of console initscript on xen-image (*)</li>
+ <li>Change xen-image boot fstype to ext2 (*)</li>
+ </ul>
+ </ul>
+ </p>
+ <p>
+ (*) These changes have only effect on new installations of IPFire.
+ </p>",
+
+ "de" : "<p>Heute werden wir <strong>Core 35</strong> veröffentlichen.
+ Es bringt die folgenden Änderungen mit sich:</p>
+ <p>
+ <ul>
+ <li>Die neuesten <strong>Sicherheitspatches</strong> für squidGuard wurden eingespielt,
+ diese beheben ein Pufferüberlauf und verhindert das squidGuard in den
+ \"Emergency-Mode\" bei überlangen URLs geht</li>
+ <li>Fehlende Module für intersil/prism wurden hinzugefügt.</li>
+ <li>Der connscheduler ist nun immer zuerst abgeschaltet (*)</li>
+ <li>Unbenutzte Blöcke in den Flash und Xen-Images vor dem komprimieren gelöscht (*)</li>
+ <li>Korrektur der Ländercodeliste (Danke m.a.d)</li>
+ </ul>
+ <ul>
+ <li>Webinterface:</li>
+ <ul>
+ <li>Der Link für die externe Snort SID Seite wurde korrigiert</li>
+ </ul>
+ <li>Ausgehende Firewall:</li>
+ <ul>
+ <li>Alte Regeln (vor Core34) werden nun korrekt geparst und für den Modus 1 wurde das Logging aktiviert</li>
+ <li>Die Protokolle GRE und ESP wurden der Ausgehenden Firewall hinzugefügt</li>
+ </ul>
+ <li>Xen:</li>
+ <ul>
+ <li>Die Fehler vom klogd Demon im Xen-Kernel wurden behoben</li>
+ <li>Der Start der Konsolen Initskripten auf dem Xen-Image wurde herausgenommen (*)</li>
+ <li>Filesystemtyp der Bootpartition des Xen-Images wurde auf ext2 geändert (*)</li>
+ </ul>
+ </ul>
+ </p>
+ <p>
+ (*) Diese Änderungen betreffen nur Neuinstallationen von IPFire.
+ </p>"}}
}
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import time
-
-import web
-import web.elements
-import web.javascript
-
-from web.info import Info
-info = Info()
-
-def size(file):
- size = os.path.getsize(file)
- suffixes = [("B",2**10), ("K",2**20), ("M",2**30), ("G",2**40), ("T",2**50)]
- for suf, lim in suffixes:
- if size > lim:
- continue
- else:
- return "%s%s" % (round(size/float(lim/2**10),2), suf)
-
-
-class Build(object):
- def __init__(self, path, basedir, url):
- self.path = path
- self.basedir = basedir
- self.url = os.path.join(url, path[len(basedir)+1:])
-
- # Read .buildinfo
- f = open("%s/.buildinfo" % path)
- self.info = f.readlines()
- f.close()
-
- def __repr__(self):
- return "<Build %s>" % self.path
-
- def __cmp__(self, other):
- return cmp(float(other.get("date")), float(self.get("date")))
-
- def get(self, key):
- key = key.upper() + "="
- for line in self.info:
- if line.startswith(key):
- return line.split("=")[1].rstrip("\n")
- return None
-
- @property
- def hostname(self):
- return self.get("hostname")
-
- @property
- def release(self):
- return self.get("release")
-
- @property
- def date(self):
- return time.strftime("%Y-%m-%d %H:%M", time.localtime(float(self.get("date"))))
-
- @property
- def arch(self):
- return self.get("arch")
-
- @property
- def duration(self):
- if not self.get("duration") or self.get("duration") == "":
- return "--:--"
- return time.strftime("%H:%M", time.gmtime(float(self.get("duration"))))
-
- @property
- def iso(self):
- return self.get("iso")
-
- @property
- def packages(self):
- path = "%s/packages_%s" % (self.path, self.arch,)
- if not os.path.exists(path):
- return []
- return os.listdir(path)
-
- @property
- def pxe(self):
- dir = "/srv/www/ipfire.org/pxe"
- for iso in os.listdir(dir):
- # Skip non-iso files
- if not iso.endswith(".iso"):
- continue
- if os.readlink(os.path.join(dir, iso)) == os.path.join(self.path, self.iso):
- return "[PXE]"
- return ""
-
-
-class Content(web.Content):
- def __init__(self):
- web.Content.__init__(self)
-
- self.builds = []
- for location in info["nightly_builds"]:
- # Only process correctly configured locations
- if not location.has_key("path") or not location.has_key("url"):
- continue
-
- # Continue if path does not exist
- if not os.path.exists(location["path"]):
- continue
-
- for (dir, subdirs, files) in os.walk(location["path"]):
- if not os.path.exists("%s/.buildinfo" % dir):
- continue
- self.builds.append(Build(dir, location["path"], location["url"]))
- self.builds.sort()
-
- def __call__(self, lang):
- today = time.strftime("%A, %Y-%m-%d", time.localtime())
- last_day = ""
-
- ret = """<h3>Nightly builds</h3>
- <table id="builds">
- <!-- <thead>
- <tr>
- <th> </th>
- <th>Release</th>
- <th>Host & Date</th>
- <th>Download</th>
- </tr>
- </thead> -->
- <tbody>"""
-
- # if there are no builds
- if not self.builds:
- ret += """<tr class="headline"><td colspan="6">There are currently no builds available.</td></tr>"""
-
- else:
- for build in self.builds:
- # write headers
- day = time.strftime("%A, %Y-%m-%d", time.localtime(float(build.get("date"))))
- if day != last_day:
- if day == today:
- ret += """<tr class="headline"><td colspan="5">Today</td></tr>"""
- else:
- ret += """<tr class="headline"><td colspan="5"> <br /> <br />%s</td></tr>""" % day
- last_day = day
-
- ret += """<tr class="build">
- <td><a href="%s" target="_blank">""" % build.url
-
- if day == today:
- ret += """<img src="/images/icons/ipfire.png" alt="IPFire" /></a></td>"""
- else:
- ret += """<img src="/images/icons/ipfire_sw.png" alt="IPFire" /></a></td>"""
-
- ret += """\
- <td> <br />
- <strong>%(release)s</strong> (%(arch)s) %(pxe)s<br />
- <a href="%(url)s/%(iso)s">%(iso)s</a> %(size_iso)s</td>
- <td> <br />
- %(hostname)s<br />
- %(date)s [%(duration)sh]</td>
- <td class="packages">%(num_packages)s <a href="%(url)s/packages_%(arch)s/" target="_blank">[PAKS]</a></td>
- </tr>""" % { "release" : build.release,
- "hostname" : build.hostname,
- "arch" : build.arch,
- "date" : build.date,
- "duration" : build.duration,
- "url" : build.url,
- "iso" : build.iso,
- "size_iso" : size(os.path.join(build.path, build.iso)),
- "num_packages" : len(build.packages),
- "pxe" : build.pxe }
-
- ret += """\
- </tbody>
- </table>"""
-
- return ret
-
-
-page = web.Page()
-page.content = Content()
-page.sidebar = web.elements.DevelopmentSidebar()
-
-### Disabled because it looks awful
-#page.javascript = web.javascript.Javascript(jquery=1)
-#page.javascript.jquery_plugin("alternate")
-#page.javascript.write("""
-# <script type="text/javascript">
-# $(function() {
-# $("#builds tbody tr.build").alternate({odd:'odd', even:'even'});
-# });
-# </script>
-#""")
+++ /dev/null
-#!/usr/bin/python
-
-import web
-import web.elements
-from web.javascript import Javascript
-
-class Content(web.Content):
- def __init__(self):
- web.Content.__init__(self)
-
- def __call__(self, lang):
- ret = """<h3>Icecream Cluster Monitoring</h3>
- <p>Cluster's CPU load: <span id="loadbar"></span> - Job load: <span id="jobbar"></span></p>
- <table id="nodes">
- <thead>
- <tr>
- <th class="hostname">Name</th>
- <th class="arch">Arch</th>
- <th class="load">Load</th>
- <th class="jobs">Jobs</th>
- <th class="speed">Speed</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <p> <br />Number of nodes: <span id="count">-</span></p>"""
-
- return ret
-
-page = web.Page()
-page.content = Content()
-page.sidebar = web.elements.DevelopmentSidebar()
-
-page.javascript = Javascript(jquery=1)
-page.javascript.jquery_plugin("progressbar")
-page.javascript.write("""<script type="text/javascript">
- nodes = new Array();
- id = 0;
- busy = false;
-
- update = function() {
- $.getJSON("/rpc.py", { method: "cluster_get_info", id : id++ },
- function(data) {
- // If we are already busy then exit
- if (busy == true) return;
-
- var count = 0;
-
- if (data.error != "null") return;
-
- busy = true;
-
- $.each(data.result.nodes, function(i, node) {
- var nodeid = node.hostname.replace(/\./g, "");
- count++;
-
- nodes[nodeid] = true;
-
- if ($("#" + nodeid).length) {
- $("#" + nodeid + "_speed").html(node.speed);
- } else {
- row = "<tr id=\\"" + nodeid + "\\" class=\\"node\\">";
- row += " <td id=\\"" + nodeid + "_hostname\\"></td>";
- row += " <td id=\\"" + nodeid + "_arch\\">" + node.arch + "</td>";
- row += " <td><span id=\\"" + nodeid + "_loadbar\\"></span></td>";
- row += " <td><span id=\\"" + nodeid + "_jobs\\"></span></td>";
- row += " <td id=\\"" + nodeid + "_speed\\">" + node.speed + "</td>";
- row += "</tr>";
- $("#nodes").append(row);
- }
- $("#" + nodeid + "_loadbar").progressBar(node.load, {showText: false});
- $("#" + nodeid + "_jobs").progressBar(node.jobcount.split("/")[0], { max: node.jobcount.split("/")[1], textFormat: 'fraction'});
- if (node.installing == true) {
- $("#" + nodeid + "_hostname").html(node.hostname + " *");
- } else {
- $("#" + nodeid + "_hostname").html(node.hostname);
- }
- });
-
- $("#loadbar").progressBar(data.result.cluster.load);
- $("#jobbar").progressBar(data.result.cluster.jobcount.split("/")[0], { max: data.result.cluster.jobcount.split("/")[1], textFormat: 'fraction'});
- for (var nodeid in nodes) {
- if (nodes[nodeid] == false) {
- $("#" + nodeid).remove();
- nodes.pop(nodeid);
- } else {
- nodes[nodeid] = false;
- }
- }
- $("#count").html(count);
- busy = false;
- });
- }
-
- $(document).ready(function(){
- // Init loadbar
- $("#loadbar").progressBar();
-
- update();
- setInterval("update()", 2000);
- })
- </script>""")
+++ /dev/null
-#!/usr/bin/python
-
-SOURCE_BASE="/srv/sources"
-SOURCE_HASHES="/srv/www/ipfire.org/source/hashes.db"
-
-SOURCE_URL="http://source.ipfire.org"
-
-import os
-import sha
-from pysqlite2 import dbapi2 as sqlite
-
-import web
-import web.elements
-
-class SourceObject:
- def __init__(self, db, file):
- self.file = file
- self.name = os.path.basename(file)
-
- if db:
- self.db = db
- else:
- self.db = sqlite.connect(SOURCE_HASHES)
- c = self.db.cursor()
- c.execute("CREATE TABLE IF NOT EXISTS hashes(file, sha1)")
- c.close()
-
- def data(self):
- f = open(self.file, "rb")
- data = f.read()
- f.close()
- return data
-
- def getHash(self, type="sha1"):
- hash = None
- c = self.db.cursor()
- c.execute("SELECT %s FROM hashes WHERE file = '%s'" % (type, self.name,))
- try:
- hash = c.fetchone()[0]
- except TypeError:
- pass
- c.close()
-
- if not hash:
- hash = sha.new(self.data()).hexdigest()
- c = self.db.cursor()
- c.execute("INSERT INTO hashes(file, sha1) VALUES('%s', '%s')" % \
- (self.name, hash,))
- c.close()
- self.db.commit()
- return hash
-
-
-class Content(web.Content):
- def __init__(self):
- web.Content.__init__(self)
-
- self.dirs = []
-
- # Open database
- db = sqlite.connect(SOURCE_HASHES)
-
- for dir, subdirs, files in os.walk(SOURCE_BASE):
- if not files:
- continue
- fileobjects = []
- files.sort()
- for file in files:
- file = os.path.join(dir, file)
- fileobjects.append(SourceObject(db, file))
- self.dirs.append((os.path.basename(dir), fileobjects))
-
- def __call__(self, lang):
- ret = ""
- self.w("<h3>IPFire Source Base</h3>")
- for dir, files in self.dirs:
- b = web.elements.Box(dir)
- b.w("<ul>")
- for file in files:
- b.w("""<li style="font-family: courier;">%(hash)s | <a href="%(url)s/%(dir)s/%(file)s">%(file)s</a></li>""" % \
- { "file" : file.name,
- "hash" : file.getHash() or "0000000000000000000000000000000000000000",
- "dir" : dir,
- "url" : SOURCE_URL, })
- b.w("</ul>")
- ret += b()
- return ret
-
-page = web.Page()
-page.content = Content()
-page.sidebar = web.elements.DevelopmentSidebar()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import os
-from xml.dom.minidom import parseString
-
-import web
-from web.banners import Banners
-from web.elements import Box, Releases
-from web.news import News
-
-class Xml(object):
- def __init__(self, file):
- file = "%s/pages/static/%s.xml" % (os.getcwd(), file,)
- f = open(file)
- data = f.read()
- f.close()
-
- self.xml = parseString(data).getElementsByTagName("Site")[0]
-
- def getAttribute(self, node, attr):
- return node.getAttribute(attr).strip()
-
- def getText(self, node):
- ret = ""
- for i in node.childNodes:
- ret += i.data
- return ret.encode("utf-8")
-
-
-class Content(Xml):
- def __init__(self, file,):
- Xml.__init__(self, file)
-
- def __call__(self, lang="en"):
- ret = ""
- for paragraphs in self.xml.getElementsByTagName("Paragraphs"):
- for paragraph in paragraphs.getElementsByTagName("Paragraph"):
- if self.getAttribute(paragraph, "news") == "1":
- news = News(int(self.getAttribute(paragraph, "count")))
- ret += news(lang).encode("utf-8")
- continue
-
- # Heading
- for heading in paragraph.getElementsByTagName("Heading"):
- if self.getAttribute(heading, "lang") == lang or \
- not self.getAttribute(heading, "lang"):
- heading = self.getText(heading)
- break
-
- b = Box(heading)
-
- # Content
- for content in paragraph.getElementsByTagName("Content"):
- if self.getAttribute(content, "lang") == lang or \
- not self.getAttribute(content, "lang"):
- if self.getAttribute(content, "raw") == "1":
- s = self.getText(content)
- else:
- s = "<p>%s</p>" % self.getText(content)
- b.w(s)
-
- ret += b()
- return ret
-
-
-class Sidebar(Xml):
- def __init__(self, file):
- Xml.__init__(self, file)
-
- def __call__(self, lang="en"):
- ret = ""
- sidebar = self.xml.getElementsByTagName("Sidebar")[0]
- for paragraph in sidebar.getElementsByTagName("Paragraph"):
- if self.getAttribute(paragraph, "banner") == "1":
- b = Banners()
- ret += """<h4>%(title)s</h4><a href="%(link)s" target="_blank">
- <img class="banner" src="%(uri)s" /></a>""" % b.random()
- continue
- elif self.getAttribute(paragraph, "releases") == "1":
- r = Releases()
- ret += r(lang)
- continue
-
- # Heading
- for heading in paragraph.getElementsByTagName("Heading"):
- if self.getAttribute(heading, "lang") == lang or \
- not self.getAttribute(heading, "lang"):
- heading = self.getText(heading)
- break
-
- ret += "<h4>%s</h4>" % heading
-
- # Content
- for content in paragraph.getElementsByTagName("Content"):
- if self.getAttribute(content, "lang") == lang or \
- not self.getAttribute(content, "lang"):
- if self.getAttribute(content, "raw") == "1":
- s = self.getText(content)
- else:
- s = "<p>%s</p>" % self.getText(content)
- ret += s
-
- return ret
-
-class Javascript(Xml):
- def __init__(self, file):
- Xml.__init__(self, file)
-
- def __call__(self, lang="en"):
- ret = ""
- scripts = self.xml.getElementsByTagName("Script")
- for script in scripts:
- ret += self.getText(script)
-
- return ret
-
-
-
-page = web.Page()
-page.content = Content(page.site)
-page.sidebar = Sidebar(page.site)
-page.javascript = Javascript(page.site)
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Downloads</Title>
- <Title lang="de">Downloads</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading lang="en">ancient Downloads</Heading>
- <Heading lang="de">ältere Downloads</Heading>
-
- <Content raw="1"><![CDATA[
- <img src="/images/box_ipfire.png" class="floatTL" alt="Download" />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- Here you can find all the old downloads of the ipfire project.<br />
- The release of <b>2.5</b> and the
- good old stables <b>2.3</b>, <b>2.1</b> and <b>1.4.9</b>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Hier findet ihr alle alten Downloads des IPFire-Projektes.<br />
- Die stabile Version <b>2.5</b> sowie die guten alten
- Versionen <b>2.3</b>, <b>2.1</b> und <b>1.4.9</b>.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- We would like to say thanks to all the people that support this project by
- lending their bandwidth.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Ebenso möchten wir uns an dieser Stelle bei den Personen bedanken, die die zahlreichen Mirrorserver
- für das Projekt zur Verfügung stellen.
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading>IPFire 2.5 Core 33</Heading>
-
- <Content lang="en"><![CDATA[
- This is the ISO of core update <strong>33</strong>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Das ist das ISO vom Core Update <strong>33</strong>.
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/torrent/ipfire-2.5.i586-full-core33.iso.torrent">IPFire 2.5 core33 - TORRENT - DISK</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core33.iso">IPFire 2.5 core33 - HTTP - DISK</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core33.iso.md5">MD5</a><br /><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-hdd.i586-full-core33.img.gz">IPFire 2.5 core33 - HTTP - USB (HDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-hdd.i586-full-core33.img.gz.md5">MD5</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-fdd.i586-full-core33.img.gz">IPFire 2.5 core33 - HTTP - USB (FDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-fdd.i586-full-core33.img.gz.md5">MD5</a><br /><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5.xen.i586-full-core33.tar.bz2">IPFire 2.5 core33 - XEN </a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.xen.i586-full-core33.tar.bz2.md5">MD5</a><br /><br />
- </div>
- ]]></Content>
- <Content lang="en"><![CDATA[
- <div align="right">
- For <a href="http://www.pcengines.ch" target="_blank" >Alix Boards</a>: <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core33.img.gz">IPFire 2.5 core33 - HTTP - FLASH 1G</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core33.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div align="right">
- Für <a href="http://www.pcengines.ch" target="_blank" >Alix Boards</a>: <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core33.img.gz">IPFire 2.5 core33 - HTTP - FLASH 1G</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core33.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading>IPFire 2.5</Heading>
-
- <Content lang="en"><![CDATA[
- This is the <strong>stable</strong> 2.5 with kernel 2.6.27.25.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Die <strong>stabile</strong> Version vom 22. Juni 2009 mit Kernel 2.6.27.25.
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/torrent/ipfire-2.5.i586-full-core28.iso.torrent">IPFire 2.5 - TORRENT - DISK</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core28.iso">IPFire 2.5 - HTTP - DISK</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core28.iso.md5">MD5</a><br /><br />
-
-<!-- DIESE DATEI IST FEHLERHAFT
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-hdd.i586-full-core28.img.gz">IPFire 2.5 - HTTP - USB (HDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-hdd.i586-full-core28.img.gz.md5">MD5</a><br />
--->
-
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-fdd.i586-full-core28.img.gz">IPFire 2.5 - HTTP - USB (FDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-fdd.i586-full-core28.img.gz.md5">MD5</a><br /><br />
- </div>
- ]]></Content>
- <Content lang="en"><![CDATA[
- <div align="right">
- For <a href="http://www.pcengines.ch" target="_blank" >Alix Boards</a>: <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core28.img.gz">IPFire 2.5 - HTTP - FLASH 1G</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core28.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div align="right">
- Für <a href="http://www.pcengines.ch" target="_blank" >Alix Boards</a>: <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core28.img.gz">IPFire 2.5 - HTTP - FLASH 1G</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core28.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading>IPFire 2.3</Heading>
-
- <Content lang="en"><![CDATA[
- This is the <strong>old stable</strong> 2.3 with kernel 2.6.25.19.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Die alte <strong>stabile</strong> Version vom 8. November 2008 mit Kernel 2.6.25.19.
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/torrent/ipfire-2.3.i586-full.iso.torrent">IPFire 2.3 - TORRENT - DISK</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.3.i586-full.iso">IPFire 2.3 - HTTP - DISK</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.3.i586-full.iso.md5">MD5</a><br /><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.3-install-usb-hdd.i586.img.gz">IPFire 2.3 - HTTP - USB (HDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.3-install-usb-hdd.i586.img.gz.md5">MD5</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.3-install-usb-fdd.i586.img.gz">IPFire 2.3 - HTTP - USB (FDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.3-install-usb-fdd.i586.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading>IPFire 2.1</Heading>
-
- <Content lang="en"><![CDATA[
- This is the old stable 2.1 with kernel 2.6.16.57.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Die stabile Version vom 8. November 2007 mit Kernel 2.6.16.57.
- ]]></Content>
- <Content lang="en"><![CDATA[
- <b>The team recommends using IPFire 2.3.</b>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>Das Team empfielt den Einsatz von IPFire 2.3.</b>
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/torrent/ipfire-2.1.i586-full.iso.torrent">IPFire 2.1 - TORRENT - DISK</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.1.i586-full.iso">IPFire 2.1 - HTTP - DISK</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.1.i586-full.iso.md5">MD5</a><br /><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.1-install-usb-hdd.i586.img.gz">IPFire 2.1 - HTTP - USB (HDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.1-install-usb-hdd.i586.img.gz.md5">MD5</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.1-install-usb-fdd.i586.img.gz">IPFire 2.1 - HTTP - USB (FDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.1-install-usb-fdd.i586.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading>IPFire 1.4.9</Heading>
-
- <Content lang="en"><![CDATA[
- The final version was released in August 2005.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Die finale Version des IPFire wurde im August 2005 veröffentlicht.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- <b>After 4 years, the team has decided to cease support for this release.</b>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>Nach 4 Jahren produktivem Einsatz hat das Team sich entschlossen<br />
- den Support für diese Version einzustellen.</b>
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/torrent/IPFire-1.4.9-FINAL.iso.torrent">IPFire 1.4.9 - TORRENT</a><br />
- <a href="http://download.ipfire.org/iso/IPFire-1.4.9-FINAL.iso">IPFire 1.4.9 - HTTP</a>
- <a href="http://download.ipfire.org/iso/IPFire-1.4.9-FINAL.iso.md5">MD5</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- </Paragraphs>
-
- <Sidebar>
- <Paragraph releases="1" />
-
- <Paragraph>
- <Heading lang="en"><![CDATA[<span>Torrent</span> clients]]></Heading>
- <Heading lang="de"><![CDATA[<span>Torrent</span> Clients]]></Heading>
-
- <Content raw="1"><![CDATA[
- <ul class="links">
- <li class="first"><img src="/images/win_icon.png" alt="Windows" align="absmiddle"><img src="/images/mac_icon.png" alt="Mac OS" align="absmiddle"> <a href="http://www.utorrent.com/" target="_blank"> µtorrent</a></li>
- <li><img src="/images/linux_icon.png" alt="Linux" align="absmiddle"><img src="/images/mac_icon.png" alt="Mac OS" align="absmiddle"> <a href="http://www.transmissionbt.com/" target="_blank">Transmission</a></li>
- </ul>
- ]]></Content>
- </Paragraph>
-
- <Paragraph banner="1" />
-
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title>CeBIT-Special</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading lang="en">IPFire on CeBIT 2010</Heading>
- <Heading lang="de">IPFire auf der CeBIT 2010</Heading>
-
- <Content><![CDATA[
- <img class="floatTR" src="/images/cebit-177px_schatten.png" alt="CeBIT" />
- ]]>
- </Content>
-
- <Content lang="en"><![CDATA[
- <strong>CeBIT</strong> 2010 will be here soon, beginning March 2nd and lasting until
- March 6th in Hannover, Germany. This year will prove to be a special
- one, as <strong>IPFire</strong> will be represented by its very own booth in
- the <strong>Open Source Project Lounge</strong>.
- </p>
-
- <p>
- First of all, our very special thanks go out to
- <a href="http://www.linuxnewmedia.de/Produkte/Events" target="_blank">Linux New Media AG</a> and
- <a href="http://www.cebit.de/opensource_d" target="_blank">Messegesellschaft</a>,
- who offer free booths to selected Open Source
- projects. <strong>CeBIT</strong> (a German acronym for the Center for Office and
- Information Technology) is the biggest computer and telecommunications
- exhibition in the world. This an excellent chance for IPFire to gain
- recognition, get in touch with users and developers, and possibly find
- sponsors and forge alliances.
- </p>
- <p>
- And, it is also a chance for all of you to meet the members of the
- <strong>IPFire</strong> community in person.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Vom <em>2. bis 6. März 2010</em> findet die <strong>CeBIT</strong> in Hannover statt.
- Das Besondere in diesem Jahr: <strong>IPFire</strong> wird mit einem
- kleinen Stand in der <strong>Open Source Project Lounge</strong> auf der Messe vertreten sein.
- </p>
-
- <p>
- Zuallererst gebührt unser Dank der
- <a href="http://www.linuxnewmedia.de/Produkte/Events" target="_blank">Linux New Media AG</a>
- und der <a href="http://www.cebit.de/opensource_d" target="_blank">Messegesellschaft</a>,
- welche für ausgewählte OpenSource-Projekte einige kostenlose Stände zur Verfügung stellen.
- Die <strong>CeBIT</strong> ist immernoch die weltgrößte Computer- und Telekommunikationsmesse,
- und diese Präsentationsmöglichkeit ist natürlich eine riesige Chance, das Projekt bekannter
- zu machen, mehr Nutzer und Entwickler zu erreichen, bzw. Kontakte zu knüpfen und Allianzen
- zu schmieden.
- </p>
-
- <p>
- Ebenfalls erhaltet Ihr die einmalige Chance die Entwickler einmal persönlich kennen zu lernen,
- Ideen auszutauschen, und und und...
- </p>]]>
- </Content>
- </Paragraph>
- <Paragraph>
- <Heading lang="en">Your Donations are Needed!</Heading>
- <Heading lang="de">Spendenaufruf</Heading>
-
- <Content><![CDATA[
- <img class="floatTL" src="/images/paypal-folder.png" alt="Paypal" />
- ]]>
- </Content>
- <Content lang="en"><![CDATA[
- This project is driven and maintained by volunteers in their free time.
- The same goes to the booth. Even though it is being donated there are
- still many costs associated with running a booth, such as flyers, CDs,
- posters and other merchandise.
- </p>
- <p>
- As we strive to represent <strong>IPFire</strong> as professionally,
- we are asking for some extra help to take advantage of this opportunity.
- All we ask is a small donation, as every little bit helps. This is a unique
- opportunity to gain international recognition for the project, so your
- money will be well spent.
- </p>
- <p>
- Materials we will be purchasing:
- </p>
- <p>
- <ul>
- <li>Posters</li>
- <li>Flyers</li>
- <li>Discs (pressed)</li>
- <li>T-Shirts, etc.</li>
- </ul>
- </p>
-
- <p>
- Our favorite way for a donation is <strong>PayPal</strong> because
- it is fast and easy. If you prefer a bank donation, please send
- us a short <a href="mailto:michael.tremer@ipfire.org" class="mail JSnocheck" title="michael.tremer@ipfire.org">request</a>
- for our bank account number.
- </p>
- <div align="center">
- <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
- <input type="hidden" name="cmd" value="_s-xclick">
- <input type="hidden" name="hosted_button_id" value="10718640">
- <input type="image" src="https://www.paypal.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
- <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
- </form>
- </div>
- ]]></Content>
-
- <Content lang="de"><![CDATA[
- Dieses Projekt wird von Freiwilligen in ihrer Freizeit betrieben und betreut, was auch
- für den Stand zutrifft. Man glaubt es kaum, aber selbst, wenn man einen kostenlosen
- Stand zur Verfügung gestellt bekommt, entstehen hohe Kosten für Flyer, CDs, Poster und
- sonstige Merchandise-Artikel.
- </p>
- <p>
- Wir möchten jedoch <strong>IPFire</strong> so professioniell wie möglich präsentieren, daher ergeht
- an euch Alle ein <strong>Spenden- und Mitmachaufruf</strong>.<br />
- Wir möchten diese einmalige Chance nutzen und <strong>IPFire</strong> noch bekannter machen.
- </p>
- <p>
- Spenden müssen nicht unbedingt finanzieller Natur sein. Es wird auch folgendes benötigt:
- </p>
-
- <p>
- <ul>
- <li>Poster</li>
- <li>Flyer</li>
- <li>CD-ROMs (bedruckt) in großer Auflage</li>
- <li>Textilien mit Aufdruck</li>
- </ul>
- </p>
-
- <p>
- Wegen des einfachen Ablaufs der Spende bevorzugen wir <strong>PayPal</strong>.
- Auf <a href="mailto:michael.tremer@ipfire.org" class="mail JSnocheck" title="michael.tremer@ipfire.org">Anfrage</a>
- kann eine Ãœberweisung auch per Kontonummer erfolgen.
- </p>
- <div align="center">
- <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
- <input type="hidden" name="cmd" value="_s-xclick">
- <input type="hidden" name="hosted_button_id" value="10718640">
- <input type="image" src="https://www.paypal.com/de_DE/DE/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
- <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
- </form>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading lang="en">Sponsors</Heading>
- <Heading lang="de">Sponsoren</Heading>
-
- <Content><![CDATA[
- <a href="http://www.linuxnewmedia.de/" target="_blank"><img src="/images/linux_new_media_ag.jpg" alt="Linux New Media AG" /></a>
- <a href="http://www.aktinet.de/" target="_blank"><img src="/images/aktinet_logo.jpg" alt="Aktinet IT-Services" /></a>
- ]]></Content>
- </Paragraph>
- </Paragraphs>
-
- <Sidebar>
- <Paragraph>
- <Heading><![CDATA[<span>Ce</span>BIT]]></Heading>
- <Content lang="en"><![CDATA[
- <ul class="links">
- <li class="first"><a href="#IPFire on CeBIT 2010:">CeBIT 2010</a></li>
- <li><a href="#Your Donations are Needed!">Donation!</a></li>
- <li><a href="#Sponsors">Sponsors</a></li>
- </ul>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <ul class="links">
- <li class="first"><a href="#IPFire auf der CeBIT 2010">CeBIT 2010</a></li>
- <li><a href="#Spendenaufruf">Spenden!</a></li>
- <li><a href="#Sponsoren">Sponsoren</a></li>
- </ul>
- ]]></Content>
-
- </Paragraph>
-
- <Paragraph banner="1" />
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Development</Title>
- <Title lang="de">Development</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading>Development</Heading>
- <Content raw="1"><![CDATA[
- <img src="../images/development.png" class="floatTR" alt="Download" />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- Welcome to the development area of the ipfire-project.<br />
- These are the development ressources. The neccessary howtos<br />
- are in the wiki.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Willkommen im Entwicklungsbereich des IPFire-Projektes.<br />
- Hier habt Ihr Zugriff auf alle Ressourcen für die Entwicklung.<br />
- Die nötigen Howtos entnehmt bitte dem Wiki.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- <br />There is one early development version at the moment:<br />
- <strong>version 3.0</strong>, the next major release, has
- reached alpha state. See the roadmap at:
- <a href="http://wiki.ipfire.org/en/development/3.0" target="_blank">http://wiki.ipfire.org/en/development/3.0</a>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- <br />Zurzeit gibt eine frühe Entwicklungsversion:<br />
- <strong>Version 3.0</strong>, die nächste Major-Version, hat
- den Alpha-Status erreicht. Ein Roadmap findet sich unter
- <a href="http://wiki.ipfire.org/de/development/3.0" target="_blank">http://wiki.ipfire.org/de/development/3.0</a>.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- <br /><a href="http://www.ohloh.net/projects/compare?metric=Activity&project_0=IPFire&project_1=Smoothwall&project_2=IPCop+Firewall" target="_blank">Comparison of IPFire to IPCop and Smoothwall on ohloh.net</a>
- ]]></Content>
-
- <Content lang="de"><![CDATA[
- <br /><a href="http://www.ohloh.net/projects/compare?metric=Activity&project_0=IPFire&project_1=Smoothwall&project_2=IPCop+Firewall" target="_blank">IPFire im Vergleich mit IPCop und Smoothwall auf ohloh.net</a>
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading>git</Heading>
- <Content lang="en"><![CDATA[
- Our source code repository is managed by
- <a href="http://git.or.cz" target="_blank">git</a>.
- Your will find a howto for working with git in our
- <a href="http://wiki.ipfire.org/en/development/git" target="_blank">wiki</a>.
- <br />
- You may also browse the our source code on: <a href="http://git.ipfire.org/" target="_blank">http://git.ipfire.org/</a>
- ]]></Content>
- <Content lang="de"><![CDATA[
- Das Quellcode-Repository wird durch
- <a href="http://git.or.cz" target="_blank">Git</a>
- verwaltet. Ein Howto zum Arbeiten mit Git findet ihr
- in unserem <a href="http://wiki.ipfire.org/de/development/git" target="_blank">Wiki</a>.
- <br />
- Browsen könnt ihr unseren Source-Code unter: <a href="http://git.ipfire.org/" target="_blank">http://git.ipfire.org/</a>
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading>source-code</Heading>
- <Content lang="en"><![CDATA[
- The source code tarballs of the in ipfire used tools are on
- <a href="http://source.ipfire.org/" target="_target">http://source.ipfire.org/</a>.<br />
- All patches that are used in our distribution are stored in a git repository.
- Therefore see "git" on this site.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Die Sourcecode-Tarballs der im IPFire verwendeten Tools findet Ihr unter
- <a href="http://source.ipfire.org/" target="_target">http://source.ipfire.org/</a><br />
- Alle Patches, die in der Distribution Verwendung finden werden in einem
- Git-Repository verwaltet. Siehe dazu Git.
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading>bugtracker</Heading>
- <Content lang="en"><![CDATA[
- We manage all issues in our <a href="http://bugtracker.ipfire.org" target="_blank">bugtracker</a>.<br />
- It is important for development to create detailed bug reports that
- we can work with them fastly.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Im <a href="http://bugtracker.ipfire.org" target="_blank">Bugtracker</a> findet Ihr bekannte Fehler.<br />
- Für die Entwicklung ist es wichtig, dass es ausführliche Bug-Reports gibt,
- die dann rasch bearbeitet werden können.
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading>nightly-builds</Heading>
- <Content lang="en"><![CDATA[
- Compiled development versions for testing purposes
- will be built (automatically).<br />
- Version 3: <a href="ftp://ftp.ipfire.org/pub/nightly-builds/" target="_blank">ftp://ftp.ipfire.org/pub/nightly-builds/</a><br />
- ]]></Content>
- <Content lang="de"><![CDATA[
- Fertig kompilierte Entwicklerversionen der aktuellen
- Entwicklungszweige werden in kurzen Abständen
- (automatisch) gebaut.<br />
- Version 3: <a href="ftp://ftp.ipfire.org/pub/nightly-builds/" target="_blank">ftp://ftp.ipfire.org/pub/nightly-builds/</a><br />
- ]]></Content>
- </Paragraph>
- </Paragraphs>
- <Sidebar>
- <Paragraph>
- <Heading><![CDATA[<span>Development</span> Zone]]></Heading>
-
- <Content lang="en"><![CDATA[
- <ul class="links">
- <li class="first"><a href="#git">git</a></li>
- <li><a href="#source-code">sourcecode</a></li>
- <li><a href="#bugtracker">bugtracker</a></li>
- <li><a href="#nightly-builds">nighty builds</a></li>
- </ul>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <ul class="links">
- <li class="first"><a href="#git">Git</a></li>
- <li><a href="#source-code">Sourcecode</a></li>
- <li><a href="#bugtracker">Bugtracker</a></li>
- <li><a href="#nightly-builds">Nighty-Builds</a></li>
- </ul>
- ]]></Content>
- </Paragraph>
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Downloads</Title>
- <Title lang="de">Downloads</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading>Downloads</Heading>
-
- <Content raw="1"><![CDATA[
- <img src="/images/box_ipfire.png" class="floatTL" alt="Download" />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- Here you can find the latest downloads of the ipfire project.<br />
- ]]></Content>
- <Content lang="de"><![CDATA[
- Hier findet ihr die neusten Downloads des IPFire-Projektes.<br />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- We would like to say thanks to all the people that support this project by
- lending their bandwidth.<br /><br /><br /><br /><br />
- ]]></Content>
- <Content lang="de"><![CDATA[
- Ebenso möchten wir uns an dieser Stelle bei den Personen bedanken, die die zahlreichen Mirrorserver
- für das Projekt zur Verfügung stellen.<br /><br /><br /><br />
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div class="button">
- <div class="button_text">
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core34.iso"> IPFire 2.5 - Core 34 </a>
- </div>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading>IPFire 2.5 (latest Core)</Heading>
-
- <Content lang="en"><![CDATA[
- This is the iso including the latest core update <strong>34</strong>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Das ist das ISO inklusive dem letzten Core Update <strong>34</strong>.
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/torrent/ipfire-2.5.i586-full-core34.iso.torrent">IPFire 2.5 core34 - TORRENT - DISK</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core34.iso">IPFire 2.5 core34 - HTTP - DISK</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.i586-full-core34.iso.md5">MD5</a><br /><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-hdd.i586-full-core34.img.gz">IPFire 2.5 core34 - HTTP - USB (HDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-hdd.i586-full-core34.img.gz.md5">MD5</a><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-fdd.i586-full-core34.img.gz">IPFire 2.5 core34 - HTTP - USB (FDD)</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5-install-usb-fdd.i586-full-core34.img.gz.md5">MD5</a><br /><br />
- <a href="http://download.ipfire.org/iso/ipfire-2.5.xen.i586-full-core34.tar.bz2">IPFire 2.5 core34 - XEN </a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.xen.i586-full-core34.tar.bz2.md5">MD5</a><br /><br />
- </div>
- ]]></Content>
- <Content lang="en"><![CDATA[
- <div align="right">
- For <a href="http://www.pcengines.ch" target="_blank" >Alix Boards</a>: <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core34.img.gz">IPFire 2.5 core34 - HTTP - FLASH 1G</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core34.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div align="right">
- Für <a href="http://www.pcengines.ch" target="_blank" >Alix Boards</a>: <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core34.img.gz">IPFire 2.5 core34 - HTTP - FLASH 1G</a>
- <a href="http://download.ipfire.org/iso/ipfire-2.5.1gb-ext2-scon.i586-full-core34.img.gz.md5">MD5</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading lang="en">ancient IPFire builds</Heading>
- <Heading lang="de">ältere IPFire Versionen</Heading>
-
- <Content lang="en"><![CDATA[
- Ancient versions can be found by browsing to <a href="ancient_download">here</a>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Ältere Versionen findet man <a href="ancient_download">hier</a>.
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading lang="en">Development builds</Heading>
- <Heading lang="de">Entwicklungsversionen</Heading>
-
- <Content lang="en"><![CDATA[
- One of us builds installation images for testing purposes regularly.
- These are ready for download, but do not use them for systems in a productive environment.
- ]]></Content>
- <Content lang="de"><![CDATA[
- In regelmäßigen Abständen wird aus dem aktuellen Quellcode
- der Entwicklungsversionen ein installationsfähiges Image, welches man downloaden kann, erstellt.
- <br />Diese Versionen dienen dem Test und sind unter Umständen nicht für den
- Produktiveinsatz geeignet.
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <div align="right">
- <a href="http://download.ipfire.org/iso/ipfire-3.0-alpha1.i686.iso">IPFire 3 - Alpha1</a>
-
- <a href="http://download.ipfire.org/iso/ipfire-3.0-alpha1.i686.iso.md5">MD5</a><br />
- </div>
- ]]></Content>
- <Content raw="1" lang="en"><![CDATA[
- <div align="right">
- <a href="builds">nightly builds</a>
- </div>
- ]]></Content>
- <Content raw="1" lang="de"><![CDATA[
- <div align="right">
- <a href="builds">Nightly Builds</a>
- </div>
- ]]></Content>
- </Paragraph>
-
- </Paragraphs>
-
- <Sidebar>
- <Paragraph releases="1" />
-
- <Paragraph>
- <Heading lang="en"><![CDATA[<span>Torrent</span> clients]]></Heading>
- <Heading lang="de"><![CDATA[<span>Torrent</span> Clients]]></Heading>
-
- <Content raw="1"><![CDATA[
- <ul class="links">
- <li class="first"><img src="/images/win_icon.png" alt="Windows" align="absmiddle"><img src="/images/mac_icon.png" alt="Mac OS" align="absmiddle"> <a href="http://www.utorrent.com/" target="_blank"> µtorrent</a></li>
- <li><img src="/images/linux_icon.png" alt="Linux" align="absmiddle"><img src="/images/mac_icon.png" alt="Mac OS" align="absmiddle"> <a href="http://www.transmissionbt.com/" target="_blank">Transmission</a></li>
- </ul>
- ]]></Content>
- </Paragraph>
-
- <Paragraph banner="1" />
-
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Imprint</Title>
- <Title lang="de">Imprint</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading>IPFire is OpenSource</Heading>
-
- <Content lang="en"><![CDATA[
- Because of the fact that the people who started this project are living
- in Germany, see the <a href="/de/imprint">german legal notes</a>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Dieses Projekt ist ein Open-Source-Projekt und verfolgt keine kommerziellen Ziele.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>Die Distribution "IPFire" steht unter der GPLv3 zur Verfügung und darf den Bedingung zufolge weitergegeben werden.</b>
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- Michael Tremer (<a href="mailto:michael@ipfire.org">michael@ipfire.org</a>)<br />
- Gerhardstrasse 8<br />
- 45711 Datteln<br /><br />
-
- Christian Schmidt (<a href="mailto:maniacikarus@ipfire.org">maniacikarus@ipfire.org</a>)<br />
- Mathildenstr. 25<br />
- 90489 Nürnberg<br /><br />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>1. Inhalt des Onlineangebotes</b><br />
- Der Autor übernimmt keinerlei Gewähr für die Aktualität, Korrektheit, Vollständigkeit
- oder Qualität der bereitgestellten Informationen. Haftungsansprüche gegen den Autor,
- welche sich auf Schäden materieller oder ideeller Art beziehen, die durch die Nutzung
- oder Nichtnutzung der dargebotenen Informationen bzw. durch die Nutzung fehlerhafter
- und unvollständiger Informationen verursacht wurden, sind grundsätzlich ausgeschlossen,
- sofern seitens des Autors kein nachweislich vorsätzliches oder grob fahrlässiges
- Verschulden vorliegt.<br />
- Alle Angebote sind freibleibend und unverbindlich. Der Autor behält es sich ausdrücklich vor,
- Teile der Seiten oder das gesamte Angebot ohne gesonderte Ankündigung zu verändern,
- zu ergänzen, zu löschen oder die Veröffentlichung zeitweise oder endgültig einzustellen.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>2. Verweise und Links</b><br />
- Bei direkten oder indirekten Verweisen auf fremde Internetseiten ("Links"),
- die außerhalb des Verantwortungsbereiches des Autors liegen, würde eine
- Haftungsverpflichtung ausschließlich in dem Fall in Kraft treten, in dem der
- Autor von den Inhalten Kenntnis hat und es ihm technisch möglich und zumutbar wäre,
- die Nutzung im Falle rechtswidriger Inhalte zu verhindern. <br />
- Der Autor erklärt hiermit ausdrücklich, dass zum Zeitpunkt der Linksetzung keine
- illegalen Inhalte auf den zu verlinkenden Seiten erkennbar waren.
- Auf die aktuelle und zukünftige Gestaltung, die Inhalte oder die Urheberschaft
- der gelinkten/verknüpften Seiten hat der Autor keinerlei Einfluss. Deshalb distanziert
- er sich hiermit ausdrücklich von allen Inhalten aller gelinkten /verknüpften Seiten,
- die nach der Linksetzung verändert wurden. Diese Feststellung gilt für alle innerhalb
- des eigenen Internetangebotes gesetzten Links und Verweise sowie für Fremdeinträge
- in vom Autor eingerichteten Gästebüchern, Diskussionsforen und Mailinglisten.
- Für illegale, fehlerhafte oder unvollständige Inhalte und insbesondere für Schäden,
- die aus der Nutzung oder Nichtnutzung solcherart dargebotener Informationen entstehen,
- haftet allein der Anbieter der Seite, auf welche verwiesen wurde, nicht derjenige,
- der über Links auf die jeweilige Veröffentlichung lediglich verweist.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>3. Urheber- und Kennzeichenrecht </b><br />
- Der Autor ist bestrebt, in allen Publikationen die Urheberrechte der verwendeten Grafiken,
- Tondokumente, Videosequenzen und Texte zu beachten, von ihm selbst erstellte Grafiken,
- Tondokumente, Videosequenzen und Texte zu nutzen oder auf lizenzfreie Grafiken, Tondokumente,
- Videosequenzen und Texte zurückzugreifen. <br />
- Alle innerhalb des Internetangebotes genannten und ggf. durch Dritte geschützten Marken-
- und Warenzeichen unterliegen uneingeschränkt den Bestimmungen des jeweils gültigen Kennzeichenrechts
- und den Besitzrechten der jeweiligen eingetragenen Eigentümer. Allein aufgrund der bloßen Nennung
- ist nicht der Schluss zu ziehen, dass Markenzeichen nicht durch Rechte Dritter geschützt sind! <br />
- Das Copyright für veröffentlichte, vom Autor selbst erstellte Objekte bleibt allein beim Autor der Seiten.
- Eine Vervielfältigung oder Verwendung solcher Grafiken, Tondokumente, Videosequenzen und Texte in
- anderen elektronischen oder gedruckten Publikationen ist ohne ausdrückliche Zustimmung des Autors nicht gestattet.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>4. Datenschutz </b><br />
- Sofern innerhalb des Internetangebotes die Möglichkeit zur Eingabe persönlicher oder geschäftlicher Daten
- (Emailadressen, Namen, Anschriften) besteht, so erfolgt die Preisgabe dieser Daten seitens
- des Nutzers auf ausdrücklich freiwilliger Basis. Die Inanspruchnahme und Bezahlung aller
- angebotenen Dienste ist - soweit technisch möglich und zumutbar - auch ohne Angabe solcher Daten
- bzw. unter Angabe anonymisierter Daten oder eines Pseudonyms gestattet. Die Nutzung der im Rahmen
- des Impressums oder vergleichbarer Angaben veröffentlichten Kontaktdaten wie Postanschriften,
- Telefon- und Faxnummern sowie Emailadressen durch Dritte zur Übersendung von nicht ausdrücklich
- angeforderten Informationen ist nicht gestattet. Rechtliche Schritte gegen die Versender von
- sogenannten Spam- Mails bei Verstössen gegen dieses Verbot sind ausdrücklich vorbehalten.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- <b>5. Rechtswirksamkeit dieses Haftungsausschlusses </b><br />
- Dieser Haftungsausschluss ist als Teil des Internetangebotes zu betrachten, von dem aus auf diese
- Seite verwiesen wurde. Sofern Teile oder einzelne Formulierungen dieses Textes der geltenden
- Rechtslage nicht, nicht mehr oder nicht vollständig entsprechen sollten, bleiben die übrigen
- Teile des Dokumentes in ihrem Inhalt und ihrer Gültigkeit davon unberührt.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- ]]></Content>
- <Content lang="de"><![CDATA[
- Dieses Impressum gilt für alle mit dem IPFire-Projekt verbundenen Webseiten (Forum, etc.).
- ]]></Content>
- </Paragraph>
- </Paragraphs>
- <Sidebar>
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Welcome</Title>
- <Title lang="de">Willkommen</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading lang="en">more security for your network</Heading>
- <Heading lang="de">mehr Sicherheit für Ihr Netzwerk</Heading>
-
- <Content lang="en"><![CDATA[
- <strong>IPFire</strong> is a linux-distribution that focusses on easy setup, good handling and a
- <strong>high niveau of security</strong>.<br /> It is operable via an intuitive webinterface, which offers a
- lot of playground for <strong>beginners</strong> and even experienced <strong>administrators</strong>.
- <strong>IPFire</strong> is maintained by experienced developers, who are really concerned about security and regulary
- updates to <strong>keep it secure</strong>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Das <strong>IPFire</strong>-System ist eine Linux-Distribution, welche die Zielsetzung hat ein einfach zu
- installierendes Grundsystem zu bieten und dabei ein <strong>hohes Sicherheitsniveau</strong> zu gewährleisten.
- <strong>IPFire</strong> ist komplett über sein intuitiv zu bedienendes Webinterface zu konfigurieren
- und bietet sowohl <strong>Anfängern</strong>, als auch erfahrenen <strong>Administratoren</strong> eine Fülle von
- Einstellungsmöglichkeiten. Ein <strong>Schwerpunkt</strong> bei der Weiterentwickling legen die erfahrenen Entwickler
- klar auf regelmäßige System und vor allem <strong>Sicherheitsupdates</strong>.<br /><br />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- <strong>IPFire</strong> ships with a custom built paket-manager called <strong>Pakfire</strong>, so the system can be
- expanded with various <a href="http://wiki.ipfire.org/en/addons/start" target="_blank">addons</a>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Durch den integrierten Paketmanager <strong>Pakfire</strong> lässt sich der <strong>IPFire</strong> mit diversen
- <a href="http://wiki.ipfire.org/de/addons/start" target="_blank">Addons</a>,
- bishin zu einem Server-System erweitern.
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- <div class="cebit_button">
- <div class="cebit_button_text">
- <a href="cebit">CeBIT-Donation</a>
- </div>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div class="cebit_button">
- <div class="cebit_button_text">
- <a href="cebit">CeBIT-Spende</a>
- </div>
- </div>
- ]]></Content>
-
- <Content raw="1"><![CDATA[
- <img src="/images/Network-1.png" alt="IPFire Logo" />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- <br /><strong>IPFire</strong> is a <strong>GPLv3</strong>-licensed project developed and maintained by
- an open <strong>community</strong> of developers.
- ]]></Content>
- <Content lang="de"><![CDATA[
- <br /><strong>IPFire</strong> ist eine freie Software, die unter der <strong>GPLv3</strong> lizensiert ist und
- von einer offenen <strong>Community</strong> entwickelt wird.
- ]]></Content>
-
- <!-- <Content raw="1"><![CDATA[
- <div class="button">
- <div class="button_text">
- <a href="download">Download IPFire 2.5</a>
- </div>
- </div>
- ]]></Content> -->
-
- </Paragraph>
-
- <Paragraph news="1" count="3" />
- </Paragraphs>
-
- <Sidebar>
- <Paragraph releases="1" />
-
- <Paragraph>
- <Heading><![CDATA[<span>Internet Relay</span> Chat]]></Heading>
- <Content><![CDATA[
- <b>Server:</b> irc.freenode.net<br />
- <b>Channel:</b> #ipfire<br />
- <a href="http://webchat.freenode.net/?channels=ipfire" target="_blank">Web-Chat</a>
- ]]></Content>
- </Paragraph>
-
- <Paragraph banner="1" />
-
- <Paragraph>
- <Heading><![CDATA[<span>RSS</span> feed]]></Heading>
-
- <Content lang="en"><![CDATA[
- <a class="feed" href="news.rss">IPFire - News</a>
- <br />
- <a href="news">news archive</a><br />]]></Content>
- <Content lang="de"><![CDATA[
- <a class="feed" href="news.rss">IPFire - News</a>
- <br />
- <a href="news">News-Archiv</a><br /><br />]]></Content>
- </Paragraph>
-
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Links</Title>
- <Title lang="de">Links</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading>Links</Heading>
- <Content raw="1"><![CDATA[
- <img src="../images/links.png" class="floatTR" alt="Links" />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- On this page, one can find a lot of external information about the <strong>IPFire-Project</strong>.
- There are some links to our partners, friends or sponsors and of course references to articles by
- some magazines.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Hier findet ihr alle relevanten Links zum Projekt IPFire. Neben Partnerseiten, Freunden und
- Sponsoren findet ihr auch Artikel über IPFire die von Benutzern oder anderen Projektseiten
- und Zeitschriften verfasst wurden.
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading>Friends of IPFire</Heading>
- <Content lang="en"><![CDATA[
- The following users do great jobs in this project. They support us by giving servers to us or
- they do mirror the web pages on their own server. Because IPFire is growing fast, we need much
- of such capacity.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Folgende unter aufgelistete User ermöglichen dem Projekt die Nutzung ihrer Server (Mirror, Build
- und Root Server). An dieser Stelle noch mal ein großes Dankeschön für euren Beitrag. Die ständig
- steigende Benutzerzahl verlangt immer schnellere Anbindungen und Datenvolumina.
- ]]></Content>
- <Content><![CDATA[
- <table>
- <tr>
- <td><a href="http://www.firewall-service.com" target="_blank">http://www.firewall-service.com</a></td>
- <td>Rene Zingel</td>
- </tr>
- <tr>
- <td><a href="http://www.rowie.at" target="_blank">http://www.rowie.at</a></td>
- <td>Ronald Wiesinger</td>
- </tr>
- <tr>
- <td><a href="http://www.scp-systems.ch" target="_blank">http://www.scp-systems.ch</a></td>
- <td>Peter Schaelchli</td>
- </tr>
- <tr>
- <td><a href="http://www.kbarthel.de" target="_blank">http://www.kbarthel.de</a></td>
- <td>Kim Barthel</td>
- </tr>
- <tr>
- <td><a href="http://ipfire.earl-net.com" target="_blank">http://ipfire.earl-net.com</a></td>
- <td>Jan Paul Tücking</td>
- </tr>
- <tr>
- <td>Seite im Aufbau</td>
- <td>Sebastian Winter</td>
- </tr>
- </table>
- <br />
- ]]></Content>
- <Content lang="en"><![CDATA[
- Marcus Scholz (Commander1024) did a <strong>talk</strong> about IPFire at the
- <em>Warpzone</em>,
- a <a href="http://www.commander1024.de/wordpress/wp-content/uploads/2009/12/IPFire-Talk.pdf">draft</a> is available as well as a <a href="http://qik.com/video/3807703">video</a>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- Marcus Scholz (Commander1024) hat einen <strong>Vortrag</strong> über IPFire in der
- <em>Warpzone</em>
- gehalten, wer will kann sich das <a href="http://www.commander1024.de/wordpress/wp-content/uploads/2009/12/IPFire-Talk.pdf">Paper</a> wie auch das <a href="http://qik.com/video/3807703">Video</a> des Vortrags anschauen.
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading lang="en">IPFire in Media</Heading>
- <Heading lang="de">IPFire in den Medien (diverse Zeitschriften)</Heading>
- <Content lang="en"><![CDATA[
- Often, there are some magazines publishing articles about IPFire.
- This is a short list to online-versions of them (Mostly in German):
- ]]></Content>
- <Content lang="de"><![CDATA[
- Immer öfter berichten uns User und Teammitglieder von diversen Zeitschriften in denen IPFire
- erwähnt wird. Hier sind Einige davon:
- ]]></Content>
- <Content><![CDATA[
- <a href="http://linuxmini.blogspot.com/2007/10/ipfire-free-firewall-for-your-home-or.html">http://linuxmini.blogspot.com/2007/10/ipfire-free-firewall-for-your-home-or.html</a><br />
- <a href="http://www.pro-linux.de/news/2006/9219.html">http://www.pro-linux.de/news/2006/9219.html</a><br />
- <a href="http://www.kriptopolis.org/ipfire">http://www.kriptopolis.org/ipfire</a><br />
- <a href="http://freedommafia.net/main/index.php?option=com_content&task=view&id=103&Itemid=47">http://freedommafia.net/main/index.php?option=com_content&task=view&id=103&Itemid=47</a><br />
- <a href="http://www.lintelligence.de/news/1026">http://www.lintelligence.de/news/1026</a><br />
- <a href="http://www.techmonkey.de/2008/09/15/ipfire-der-nachste-star-am-soho-himmel/">http://www.techmonkey.de/2008/09/15/ipfire-der-nachste-star-am-soho-himmel/</a><br />
- <a href="http://www.pcwelt.de/start/sicherheit/firewall/news/187759/ipfire_auf_version_23_aktualisiert/">http://www.pcwelt.de/start/sicherheit/firewall/news/187759/ipfire_auf_version_23_aktualisiert/</a><br />
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading lang="en">Discussion about IPFire</Heading>
- <Heading lang="de">Boards und Foren (Diskussionen über IPFire)</Heading>
- <Content lang="en"><![CDATA[
- Users' recommendations do best! - This are links to threads in boards where users talk about IPFire:
- ]]></Content>
- <Content lang="de"><![CDATA[
- Mundpropaganda sagt man, ist die beste Werbung! Hier ein paar Boards und Foren, wo man sich
- gepflegt über IPFire unterhält und Erfahrungen austauscht.
- ]]></Content>
- <Content><![CDATA[
- <a href="http://forum.linuxcast.eu/viewtopic.php?f=13&p=438">http://forum.linuxcast.eu/viewtopic.php?f=13&p=438</a><br />
- <a href="http://forum.golem.de/read.php?26129,1364598,1364598#msg-1364598">http://forum.golem.de/read.php?26129,1364598,1364598#msg-1364598</a><br />
- <a href="http://www.ipcop-forum.de/forum/viewtopic.php?f=28&t=21055&hilit=IPFire">http://www.ipcop-forum.de/forum/viewtopic.php?f=28&t=21055&hilit=IPFire</a><br />
- <a href="http://forum.cdrinfo.pl/f102/jaki-dysk-sieciowy-78524/">http://forum.cdrinfo.pl/f102/jaki-dysk-sieciowy-78524/</a><br />
- <a href="http://forum.mini-pc-pro.de/projekt-forum/3681-epia-ipcop-router-projekt-wirft-mir-diverse-fragen-auf.html">http://forum.mini-pc-pro.de/projekt-forum/3681-epia-ipcop-router-projekt-wirft-mir-diverse-fragen-auf.html</a><br />
- <a href="http://nachtwandler.blogage.de/entries/2008/10/4/IPFire">http://nachtwandler.blogage.de/entries/2008/10/4/IPFire</a><br />
- <a href="http://zahlenzerkleinerer.de/1085/der-erste-ipfire-test.html">http://zahlenzerkleinerer.de/1085/der-erste-ipfire-test.html</a><br />
- ]]></Content>
- </Paragraph>
- <Paragraph>
- <Heading lang="en">Sites that link to here</Heading>
- <Heading lang="de">Nach IPFire verlinkende Seiten</Heading>
- <Content lang="en"><![CDATA[
- We are glad to give a list of sites that link to us. So, we would do this back again:
- ]]></Content>
- <Content lang="de"><![CDATA[
- Am meisten Freuen wir uns aber über Seitenbetreiber die einen Link auf unsere Projektseite setzen,
- um auch andere User auf uns hinzuweisen. Hier ein paar davon:
- ]]></Content>
- <Content><![CDATA[
- <a href="http://www.ohloh.net/projects/ipfire">http://www.ohloh.net/projects/ipfire</a><br />
- <a href="http://forum.softgil.com/weblinks.php?cat_id=1">http://forum.softgil.com/weblinks.php?cat_id=1</a><br />
- ]]></Content>
-
- </Paragraph>
- </Paragraphs>
- <Sidebar>
- <Paragraph>
- <Heading lang="en"><![CDATA[<span>more</span> links]]></Heading>
- <Heading lang="de"><![CDATA[<span>mehr</span> links]]></Heading>
-
- <Content lang="en"><![CDATA[
- If there are relevant links on sites that are not known to the IPFire project, please let us know! (via forum or irc)<br />We are grateful for any assistance!
- ]]></Content>
- <Content lang="de"><![CDATA[
- Solltet ihr weitere relevante Links zum Projekt IPFire irgendwo entdecken, lasst es uns bitte
- wissen! (via Forum oder IRC)<br />Für jede Hilfe sind wir dankbar!
- ]]></Content>
- </Paragraph>
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title>News</Title>
- </Config>
- <Paragraphs>
- <Paragraph>
- <Heading lang="en">IPFire News Archive</Heading>
- <Heading lang="de">IPFire-News-Archiv</Heading>
-
- <Content lang="en"><![CDATA[
- In a big project like this, it might being simple to keep up
- with progress. That doesn't matter. This site will give you
- all information you need.<br />
- Additionally, you may subscribe to our
- <a class="feed" href="/en/news.rss">rss feed</a>.
- ]]></Content>
- <Content lang="de"><![CDATA[
- In einem Projekt wie IPFire ist es nicht leicht sich auf dem
- neuesten Stand zu halten. Dazu gibt es aber diese Seite, auf
- der man alles wichtige chronologisch angeordnet nachlesen kann.
- <br />
- Weiterhin gibt es einen
- <a class="feed" href="/de/news.rss">RSS-Feed</a>, der sich abbonieren
- lässt.
- ]]></Content>
- </Paragraph>
-
- <Paragraph news="1" count="50" />
- </Paragraphs>
-
- <Sidebar>
- <Paragraph banner="1" />
- </Sidebar>
-</Site>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<Site>
- <Config>
- <Title lang="en">Screenshots</Title>
- <Title lang="de">Screenshots</Title>
- </Config>
- <Script><![CDATA[
- <script src="/include/jquery.min.js" type="text/javascript"></script>
- <script type="text/javascript" src="/include/jquery.lightbox.min.js"></script>
- <script type="text/javascript">
- $(function() {
- $("#screenshots a").lightBox();
- });
- </script>
- ]]></Script>
- <Paragraphs>
- <Paragraph><Heading>Screenshots</Heading>
- <Content raw="1"><![CDATA[
- <img src="../images/screenshots/monitor.png" class="floatTR" alt="Screenshots" />
- ]]></Content>
-
- <Content lang="en"><![CDATA[
- Here you will find an insight into the IPFire webinterface.<br />
- ]]></Content>
- <Content lang="de"><![CDATA[
- Hier findet Ihr einen keinen Einblick in das IPFire Webinterface.<br />
- ]]></Content>
- </Paragraph>
-
- <Paragraph><Heading>System</Heading>
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/index_en.png" title="Home"><img src="/images/screenshots/index_en_tn.png" border="0" alt="Home"></a>
-
- <a href="/images/screenshots/backup_en.png" title="Backup"><img src="/images/screenshots/backup_en_tn.png" border="0" alt="Backup"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/index_de.png" title="Startseite"><img src="/images/screenshots/index_de_tn.png" border="0" alt="Startsete"></a>
-
- <a href="/images/screenshots/backup_de.png" title="Datensicherung"><img src="/images/screenshots/backup_de_tn.png" border="0" alt="Datensicherung"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph><Heading>Status</Heading>
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/services_en.png" title="Services"><img src="/images/screenshots/services_en_tn.png" border="0" alt="Services"></a>
-
- <a href="/images/screenshots/networkother_en.png" title="Network (other)"><img src="/images/screenshots/networkother_en_tn.png" border="0" alt="Network (other)"></a>
-
- <a href="/images/screenshots/connections_en.png" title="Connections"><img src="/images/screenshots/connections_en_tn.png" border="0" alt="Connections"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/services_de.png" title="Dienste"><img src="/images/screenshots/services_de_tn.png" border="0" alt="Dienste"></a>
-
- <a href="/images/screenshots/networkother_de.png" title="Netzwerk (sonstige)"><img src="/images/screenshots/networkother_de_tn.png" border="0" alt="Netzwerk (sonstige)"></a>
-
- <a href="/images/screenshots/connections_de.png" title="Verbindungen"><img src="/images/screenshots/connections_de_tn.png" border="0" alt="Verbindungen"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading lang="en">Network</Heading>
- <Heading lang="de">Netzwerk</Heading>
-
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/dhcp_en.png" title="DHCP Server"><img src="/images/screenshots/dhcp_en_tn.png" border="0" alt="DHCP Server"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/dhcp_de.png" title="DHCP Server"><img src="/images/screenshots/dhcp_de_tn.png" border="0" alt="DHCP Server"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph>
- <Heading lang="en">Services</Heading>
- <Heading lang="de">Dienste</Heading>
-
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/ipsec_en.png" title="IPSec"><img src="/images/screenshots/ipsec_en_tn.png" border="0" alt="IPSec"></a>
-
- <a href="/images/screenshots/qos_en.png" title="Quality of Service"><img src="/images/screenshots/qos_en_tn.png" border="0" alt="Quality of Service"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/ipsec_de.png" title="IPSec"><img src="/images/screenshots/ipsec_de_tn.png" border="0" alt="IPSec"></a>
-
- <a href="/images/screenshots/qos_de.png" title="Quality of Service"><img src="/images/screenshots/qos_de_tn.png" border="0" alt="Quality of Service"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph><Heading>Firewall</Heading>
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/outgoing_fw_en.png" title="Outgoing Firewall"><img src="/images/screenshots/outgoing_fw_en_tn.png" border="0" alt="Outgoing Firewall"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/outgoing_fw_de.png" title="Ausgehende Firewall"><img src="/images/screenshots/outgoing_fw_de_tn.png" border="0" alt="Ausgehende Firewall"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph><Heading>IPFire</Heading>
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/pakfire_en.png" title="Pakfire"><img src="/images/screenshots/pakfire_en_tn.png" border="0" alt="Pakfire"></a>
-
- <a href="/images/screenshots/samba_en.png" title="Samba"><img src="/images/screenshots/samba_en_tn.png" border="0" alt="Samba"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/pakfire_de.png" title="Pakfire"><img src="/images/screenshots/pakfire_de_tn.png" border="0" alt="Pakfire"></a>
-
- <a href="/images/screenshots/samba_de.png" title="Samba"><img src="/images/screenshots/samba_de_tn.png" border="0" alt="Samba"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- <Paragraph><Heading>Logs</Heading>
- <Content lang="en"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/fwlog_ip_en.png" title="Fw-Logdgraphs (IP)"><img src="/images/screenshots/fwlog_ip_en_tn.png" border="0" alt="Fw-Logdgraphs (IP)"></a>
-
- <a href="/images/screenshots/proxy_en.png" title="Proxy Reports"><img src="/images/screenshots/proxy_en_tn.png" border="0" alt="Proxy Reports"></a>
- </div>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <div id="screenshots">
-
- <a href="/images/screenshots/fwlog_ip_de.png" title="Fw-Logdiagramme (IP)"><img src="/images/screenshots/fwlog_ip_de_tn.png" border="0" alt="Fw-Logdiagramme (IP)"></a>
-
- <a href="/images/screenshots/proxy_de.png" title="Proxy-Berichte"><img src="/images/screenshots/proxy_de_tn.png" border="0" alt="Proxy-Berichte"></a>
- </div>
- ]]></Content>
- </Paragraph>
-
- </Paragraphs>
- <Sidebar>
- <Paragraph>
- <Heading lang="en"><![CDATA[<span>Screenshot</span> list]]></Heading>
- <Heading lang="de"><![CDATA[<span>Screenshot</span>liste]]></Heading>
-
- <Content lang="en"><![CDATA[
- <ul class="links">
- <li class="first"><a href="#System">System</a></li>
- <li><a href="#Status">Status</a></li>
- <li><a href="#Network">Network</a></li>
- <li><a href="#Services">Services</a></li>
- <li><a href="#Firewall">Firewall</a></li>
- <li><a href="#IPFire">IPFire</a></li>
- <li><a href="#Logs">Logs</a></li>
- </ul>
- ]]></Content>
- <Content lang="de"><![CDATA[
- <ul class="links">
- <li class="first"><a href="#System">System</a></li>
- <li><a href="#Status">Status</a></li>
- <li><a href="#Netzwerk">Netzwerk</a></li>
- <li><a href="#Dienste">Dienste</a></li>
- <li><a href="#Firewall">Firewall</a></li>
- <li><a href="#IPFire">IPFire</a></li>
- <li><a href="#Logs">Logs</a></li>
- </ul>
- ]]></Content>
-
- </Paragraph>
- </Sidebar>
-</Site>
\ No newline at end of file
+++ /dev/null
-#!/usr/bin/python
-
-TRACKER_URL ="http://tracker.ipfire.org:6969/stats?format=txt&mode=tpbs"
-TORRENT_BASE="/srv/pakfire/data/torrent"
-
-import os
-import sha
-import urllib2
-
-from client.bencode import bencode, bdecode
-import web
-import web.elements
-
-class TrackerInfo:
- def __init__(self, url):
- self.info = {}
-
- f = urllib2.urlopen(url)
- for line in f.readlines():
- (hash, seeds, peers,) = line.split(":")
- self.info[hash] = (seeds, peers.rstrip("\n"),)
- f.close()
-
- def __call__(self):
- print self.info
-
- def get(self, hash):
- try:
- return self.info[hash]
- except KeyError:
- return 0, 0
-
-
-class TorrentObject:
- def __init__(self, file):
- self.name = os.path.basename(file)
- f = open(file, "rb")
- self.info = bdecode(f.read())
- f.close()
-
- def __call__(self):
- print "File : %s" % self.get_file()
- print "Hash : %s" % self.get_hash()
-
- def get_hash(self):
- return sha.sha(bencode(self.info["info"])).hexdigest().upper()
-
- def get_file(self):
- return self.name
-
-
-torrent_files = []
-for file in os.listdir(TORRENT_BASE):
- if not file.endswith(".torrent"):
- continue
- file = os.path.join(TORRENT_BASE, file)
- torrent_files.insert(0, TorrentObject(file))
-
-
-tracker = TrackerInfo(TRACKER_URL)
-
-class TorrentBox(web.elements.Box):
- def __init__(self, file):
- web.elements.Box.__init__(self, file.name, file.get_hash())
- self.w("""
- <p>
- <strong>Seeders:</strong> %s<br />
- <strong>Leechers:</strong> %s
- </p>""" % tracker.get(file.get_hash()))
- self.w("""
- <p style="text-align: right;">
- <a href="http://download.ipfire.org/torrent/%s">Download</a>
- </p>""" % (file.name,))
-
-
-class Content(web.Content):
- def __init__(self):
- web.Content.__init__(self)
-
- def content(self):
- self.w("<h3>IPFire Torrent Tracker</h3>")
- for t in torrent_files:
- b = TorrentBox(t)
- self.w(b())
-
-page = web.Page()
-page.content = Content()
-page.sidebar = web.elements.Sidebar()
+++ /dev/null
-#written by John Hoffman
-
-from inifile import ini_write, ini_read
-from bencode import bencode, bdecode
-from types import IntType, LongType, StringType, FloatType
-from CreateIcons import GetIcons, CreateIcon
-from parseargs import defaultargs
-from __init__ import product_name, version_short
-import sys,os
-from time import time, strftime
-
-try:
- True
-except:
- True = 1
- False = 0
-
-try:
- realpath = os.path.realpath
-except:
- realpath = lambda x:x
-OLDICONPATH = os.path.abspath(os.path.dirname(realpath(sys.argv[0])))
-
-DIRNAME = '.'+product_name
-
-hexchars = '0123456789abcdef'
-hexmap = []
-revmap = {}
-for i in xrange(256):
- x = hexchars[(i&0xF0)/16]+hexchars[i&0x0F]
- hexmap.append(x)
- revmap[x] = chr(i)
-
-def tohex(s):
- r = []
- for c in s:
- r.append(hexmap[ord(c)])
- return ''.join(r)
-
-def unhex(s):
- r = [ revmap[s[x:x+2]] for x in xrange(0, len(s), 2) ]
- return ''.join(r)
-
-def copyfile(oldpath, newpath): # simple file copy, all in RAM
- try:
- f = open(oldpath,'rb')
- r = f.read()
- success = True
- except:
- success = False
- try:
- f.close()
- except:
- pass
- if not success:
- return False
- try:
- f = open(newpath,'wb')
- f.write(r)
- except:
- success = False
- try:
- f.close()
- except:
- pass
- return success
-
-
-class ConfigDir:
-
- ###### INITIALIZATION TASKS ######
-
- def __init__(self, config_type = None):
- self.config_type = config_type
- if config_type:
- config_ext = '.'+config_type
- else:
- config_ext = ''
-
- def check_sysvars(x):
- y = os.path.expandvars(x)
- if y != x and os.path.isdir(y):
- return y
- return None
-
- for d in ['${APPDATA}', '${HOME}', '${HOMEPATH}', '${USERPROFILE}']:
- dir_root = check_sysvars(d)
- if dir_root:
- break
- else:
- dir_root = os.path.expanduser('~')
- if not os.path.isdir(dir_root):
- dir_root = os.path.abspath(os.path.dirname(sys.argv[0]))
-
- dir_root = os.path.join(dir_root,DIRNAME)
- self.dir_root = dir_root
-
- if not os.path.isdir(self.dir_root):
- os.mkdir(self.dir_root,0700) # exception if failed
-
- self.dir_icons = os.path.join(dir_root,'icons')
- if not os.path.isdir(self.dir_icons):
- os.mkdir(self.dir_icons)
- for icon in GetIcons():
- i = os.path.join(self.dir_icons,icon)
- if not os.path.exists(i):
- if not copyfile(os.path.join(OLDICONPATH,icon),i):
- CreateIcon(icon,self.dir_icons)
-
- self.dir_torrentcache = os.path.join(dir_root,'torrentcache')
- if not os.path.isdir(self.dir_torrentcache):
- os.mkdir(self.dir_torrentcache)
-
- self.dir_datacache = os.path.join(dir_root,'datacache')
- if not os.path.isdir(self.dir_datacache):
- os.mkdir(self.dir_datacache)
-
- self.dir_piececache = os.path.join(dir_root,'piececache')
- if not os.path.isdir(self.dir_piececache):
- os.mkdir(self.dir_piececache)
-
- self.configfile = os.path.join(dir_root,'config'+config_ext+'.ini')
- self.statefile = os.path.join(dir_root,'state'+config_ext)
-
- self.TorrentDataBuffer = {}
-
-
- ###### CONFIG HANDLING ######
-
- def setDefaults(self, defaults, ignore=[]):
- self.config = defaultargs(defaults)
- for k in ignore:
- if self.config.has_key(k):
- del self.config[k]
-
- def checkConfig(self):
- return os.path.exists(self.configfile)
-
- def loadConfig(self):
- try:
- r = ini_read(self.configfile)['']
- except:
- return self.config
- l = self.config.keys()
- for k,v in r.items():
- if self.config.has_key(k):
- t = type(self.config[k])
- try:
- if t == StringType:
- self.config[k] = v
- elif t == IntType or t == LongType:
- self.config[k] = long(v)
- elif t == FloatType:
- self.config[k] = float(v)
- l.remove(k)
- except:
- pass
- if l: # new default values since last save
- self.saveConfig()
- return self.config
-
- def saveConfig(self, new_config = None):
- if new_config:
- for k,v in new_config.items():
- if self.config.has_key(k):
- self.config[k] = v
- try:
- ini_write( self.configfile, self.config,
- 'Generated by '+product_name+'/'+version_short+'\n'
- + strftime('%x %X') )
- return True
- except:
- return False
-
- def getConfig(self):
- return self.config
-
-
- ###### STATE HANDLING ######
-
- def getState(self):
- try:
- f = open(self.statefile,'rb')
- r = f.read()
- except:
- r = None
- try:
- f.close()
- except:
- pass
- try:
- r = bdecode(r)
- except:
- r = None
- return r
-
- def saveState(self, state):
- try:
- f = open(self.statefile,'wb')
- f.write(bencode(state))
- success = True
- except:
- success = False
- try:
- f.close()
- except:
- pass
- return success
-
-
- ###### TORRENT HANDLING ######
-
- def getTorrents(self):
- d = {}
- for f in os.listdir(self.dir_torrentcache):
- f = os.path.basename(f)
- try:
- f, garbage = f.split('.')
- except:
- pass
- d[unhex(f)] = 1
- return d.keys()
-
- def getTorrentVariations(self, t):
- t = tohex(t)
- d = []
- for f in os.listdir(self.dir_torrentcache):
- f = os.path.basename(f)
- if f[:len(t)] == t:
- try:
- garbage, ver = f.split('.')
- except:
- ver = '0'
- d.append(int(ver))
- d.sort()
- return d
-
- def getTorrent(self, t, v = -1):
- t = tohex(t)
- if v == -1:
- v = max(self.getTorrentVariations(t)) # potential exception
- if v:
- t += '.'+str(v)
- try:
- f = open(os.path.join(self.dir_torrentcache,t),'rb')
- r = bdecode(f.read())
- except:
- r = None
- try:
- f.close()
- except:
- pass
- return r
-
- def writeTorrent(self, data, t, v = -1):
- t = tohex(t)
- if v == -1:
- try:
- v = max(self.getTorrentVariations(t))+1
- except:
- v = 0
- if v:
- t += '.'+str(v)
- try:
- f = open(os.path.join(self.dir_torrentcache,t),'wb')
- f.write(bencode(data))
- except:
- v = None
- try:
- f.close()
- except:
- pass
- return v
-
-
- ###### TORRENT DATA HANDLING ######
-
- def getTorrentData(self, t):
- if self.TorrentDataBuffer.has_key(t):
- return self.TorrentDataBuffer[t]
- t = os.path.join(self.dir_datacache,tohex(t))
- if not os.path.exists(t):
- return None
- try:
- f = open(t,'rb')
- r = bdecode(f.read())
- except:
- r = None
- try:
- f.close()
- except:
- pass
- self.TorrentDataBuffer[t] = r
- return r
-
- def writeTorrentData(self, t, data):
- self.TorrentDataBuffer[t] = data
- try:
- f = open(os.path.join(self.dir_datacache,tohex(t)),'wb')
- f.write(bencode(data))
- success = True
- except:
- success = False
- try:
- f.close()
- except:
- pass
- if not success:
- self.deleteTorrentData(t)
- return success
-
- def deleteTorrentData(self, t):
- try:
- os.remove(os.path.join(self.dir_datacache,tohex(t)))
- except:
- pass
-
- def getPieceDir(self, t):
- return os.path.join(self.dir_piececache,tohex(t))
-
-
- ###### EXPIRATION HANDLING ######
-
- def deleteOldCacheData(self, days, still_active = [], delete_torrents = False):
- if not days:
- return
- exptime = time() - (days*24*3600)
- names = {}
- times = {}
-
- for f in os.listdir(self.dir_torrentcache):
- p = os.path.join(self.dir_torrentcache,f)
- f = os.path.basename(f)
- try:
- f, garbage = f.split('.')
- except:
- pass
- try:
- f = unhex(f)
- assert len(f) == 20
- except:
- continue
- if delete_torrents:
- names.setdefault(f,[]).append(p)
- try:
- t = os.path.getmtime(p)
- except:
- t = time()
- times.setdefault(f,[]).append(t)
-
- for f in os.listdir(self.dir_datacache):
- p = os.path.join(self.dir_datacache,f)
- try:
- f = unhex(os.path.basename(f))
- assert len(f) == 20
- except:
- continue
- names.setdefault(f,[]).append(p)
- try:
- t = os.path.getmtime(p)
- except:
- t = time()
- times.setdefault(f,[]).append(t)
-
- for f in os.listdir(self.dir_piececache):
- p = os.path.join(self.dir_piececache,f)
- try:
- f = unhex(os.path.basename(f))
- assert len(f) == 20
- except:
- continue
- for f2 in os.listdir(p):
- p2 = os.path.join(p,f2)
- names.setdefault(f,[]).append(p2)
- try:
- t = os.path.getmtime(p2)
- except:
- t = time()
- times.setdefault(f,[]).append(t)
- names.setdefault(f,[]).append(p)
-
- for k,v in times.items():
- if max(v) < exptime and not k in still_active:
- for f in names[k]:
- try:
- os.remove(f)
- except:
- try:
- os.removedirs(f)
- except:
- pass
-
-
- def deleteOldTorrents(self, days, still_active = []):
- self.deleteOldCacheData(days, still_active, True)
-
-
- ###### OTHER ######
-
- def getIconDir(self):
- return self.dir_icons
+++ /dev/null
-#written by John Hoffman
-
-from ConnChoice import *
-from wxPython.wx import *
-from types import IntType, FloatType, StringType
-from download_bt1 import defaults
-from ConfigDir import ConfigDir
-import sys,os
-import socket
-from parseargs import defaultargs
-
-try:
- True
-except:
- True = 1
- False = 0
-
-try:
- wxFULL_REPAINT_ON_RESIZE
-except:
- wxFULL_REPAINT_ON_RESIZE = 0 # fix for wx pre-2.5
-
-if (sys.platform == 'win32'):
- _FONT = 9
-else:
- _FONT = 10
-
-def HexToColor(s):
- r,g,b = s.split(' ')
- return wxColour(red=int(r,16), green=int(g,16), blue=int(b,16))
-
-def hex2(c):
- h = hex(c)[2:]
- if len(h) == 1:
- h = '0'+h
- return h
-def ColorToHex(c):
- return hex2(c.Red()) + ' ' + hex2(c.Green()) + ' ' + hex2(c.Blue())
-
-ratesettingslist = []
-for x in connChoices:
- if not x.has_key('super-seed'):
- ratesettingslist.append(x['name'])
-
-
-configFileDefaults = [
- #args only available for the gui client
- ('win32_taskbar_icon', 1,
- "whether to iconize do system try or not on win32"),
- ('gui_stretchwindow', 0,
- "whether to stretch the download status window to fit the torrent name"),
- ('gui_displaystats', 1,
- "whether to display statistics on peers and seeds"),
- ('gui_displaymiscstats', 1,
- "whether to display miscellaneous other statistics"),
- ('gui_ratesettingsdefault', ratesettingslist[0],
- "the default setting for maximum upload rate and users"),
- ('gui_ratesettingsmode', 'full',
- "what rate setting controls to display; options are 'none', 'basic', and 'full'"),
- ('gui_forcegreenonfirewall', 0,
- "forces the status icon to be green even if the client seems to be firewalled"),
- ('gui_default_savedir', '',
- "default save directory"),
- ('last_saved', '', # hidden; not set in config
- "where the last torrent was saved"),
- ('gui_font', _FONT,
- "the font size to use"),
- ('gui_saveas_ask', -1,
- "whether to ask where to download to (0 = never, 1 = always, -1 = automatic resume"),
-]
-
-def setwxconfigfiledefaults():
- CHECKINGCOLOR = ColorToHex(wxSystemSettings_GetColour(wxSYS_COLOUR_3DSHADOW))
- DOWNLOADCOLOR = ColorToHex(wxSystemSettings_GetColour(wxSYS_COLOUR_ACTIVECAPTION))
-
- configFileDefaults.extend([
- ('gui_checkingcolor', CHECKINGCOLOR,
- "progress bar checking color"),
- ('gui_downloadcolor', DOWNLOADCOLOR,
- "progress bar downloading color"),
- ('gui_seedingcolor', '00 FF 00',
- "progress bar seeding color"),
- ])
-
-defaultsToIgnore = ['responsefile', 'url', 'priority']
-
-
-class configReader:
-
- def __init__(self):
- self.configfile = wxConfig("BitTorrent",style=wxCONFIG_USE_LOCAL_FILE)
- self.configMenuBox = None
- self.advancedMenuBox = None
- self._configReset = True # run reset for the first time
-
- setwxconfigfiledefaults()
-
- defaults.extend(configFileDefaults)
- self.defaults = defaultargs(defaults)
-
- self.configDir = ConfigDir('gui')
- self.configDir.setDefaults(defaults,defaultsToIgnore)
- if self.configDir.checkConfig():
- self.config = self.configDir.loadConfig()
- else:
- self.config = self.configDir.getConfig()
- self.importOldGUIConfig()
- self.configDir.saveConfig()
-
- updated = False # make all config default changes here
-
- if self.config['gui_ratesettingsdefault'] not in ratesettingslist:
- self.config['gui_ratesettingsdefault'] = (
- self.defaults['gui_ratesettingsdefault'] )
- updated = True
- if self.config['ipv6_enabled'] and (
- sys.version_info < (2,3) or not socket.has_ipv6 ):
- self.config['ipv6_enabled'] = 0
- updated = True
- for c in ['gui_checkingcolor','gui_downloadcolor','gui_seedingcolor']:
- try:
- HexToColor(self.config[c])
- except:
- self.config[c] = self.defaults[c]
- updated = True
-
- if updated:
- self.configDir.saveConfig()
-
- self.configDir.deleteOldCacheData(self.config['expire_cache_data'])
-
-
- def importOldGUIConfig(self):
- oldconfig = wxConfig("BitTorrent",style=wxCONFIG_USE_LOCAL_FILE)
- cont, s, i = oldconfig.GetFirstEntry()
- if not cont:
- oldconfig.DeleteAll()
- return False
- while cont: # import old config data
- if self.config.has_key(s):
- t = oldconfig.GetEntryType(s)
- try:
- if t == 1:
- assert type(self.config[s]) == type('')
- self.config[s] = oldconfig.Read(s)
- elif t == 2 or t == 3:
- assert type(self.config[s]) == type(1)
- self.config[s] = int(oldconfig.ReadInt(s))
- elif t == 4:
- assert type(self.config[s]) == type(1.0)
- self.config[s] = oldconfig.ReadFloat(s)
- except:
- pass
- cont, s, i = oldconfig.GetNextEntry(i)
-
-# oldconfig.DeleteAll()
- return True
-
-
- def resetConfigDefaults(self):
- for p,v in self.defaults.items():
- if not p in defaultsToIgnore:
- self.config[p] = v
- self.configDir.saveConfig()
-
- def writeConfigFile(self):
- self.configDir.saveConfig()
-
- def WriteLastSaved(self, l):
- self.config['last_saved'] = l
- self.configDir.saveConfig()
-
-
- def getcheckingcolor(self):
- return HexToColor(self.config['gui_checkingcolor'])
- def getdownloadcolor(self):
- return HexToColor(self.config['gui_downloadcolor'])
- def getseedingcolor(self):
- return HexToColor(self.config['gui_seedingcolor'])
-
- def configReset(self):
- r = self._configReset
- self._configReset = False
- return r
-
- def getConfigDir(self):
- return self.configDir
-
- def getIconDir(self):
- return self.configDir.getIconDir()
-
- def getTorrentData(self,t):
- return self.configDir.getTorrentData(t)
-
- def setColorIcon(self, xxicon, xxiconptr, xxcolor):
- idata = wxMemoryDC()
- idata.SelectObject(xxicon)
- idata.SetBrush(wxBrush(xxcolor,wxSOLID))
- idata.DrawRectangle(0,0,16,16)
- idata.SelectObject(wxNullBitmap)
- xxiconptr.Refresh()
-
-
- def getColorFromUser(self, parent, colInit):
- data = wxColourData()
- if colInit.Ok():
- data.SetColour(colInit)
- data.SetCustomColour(0, self.checkingcolor)
- data.SetCustomColour(1, self.downloadcolor)
- data.SetCustomColour(2, self.seedingcolor)
- dlg = wxColourDialog(parent,data)
- if not dlg.ShowModal():
- return colInit
- return dlg.GetColourData().GetColour()
-
-
- def configMenu(self, parent):
- self.parent = parent
- try:
- self.FONT = self.config['gui_font']
- self.default_font = wxFont(self.FONT, wxDEFAULT, wxNORMAL, wxNORMAL, False)
- self.checkingcolor = HexToColor(self.config['gui_checkingcolor'])
- self.downloadcolor = HexToColor(self.config['gui_downloadcolor'])
- self.seedingcolor = HexToColor(self.config['gui_seedingcolor'])
-
- if (self.configMenuBox is not None):
- try:
- self.configMenuBox.Close()
- except wxPyDeadObjectError, e:
- self.configMenuBox = None
-
- self.configMenuBox = wxFrame(None, -1, 'BitTorrent Preferences', size = (1,1),
- style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
- if (sys.platform == 'win32'):
- self.icon = self.parent.icon
- self.configMenuBox.SetIcon(self.icon)
-
- panel = wxPanel(self.configMenuBox, -1)
- self.panel = panel
-
- def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
- x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
- x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
- if color is not None:
- x.SetForegroundColour(color)
- return x
-
- colsizer = wxFlexGridSizer(cols = 1, vgap = 8)
-
- self.gui_stretchwindow_checkbox = wxCheckBox(panel, -1, "Stretch window to fit torrent name *")
- self.gui_stretchwindow_checkbox.SetFont(self.default_font)
- self.gui_stretchwindow_checkbox.SetValue(self.config['gui_stretchwindow'])
-
- self.gui_displaystats_checkbox = wxCheckBox(panel, -1, "Display peer and seed statistics")
- self.gui_displaystats_checkbox.SetFont(self.default_font)
- self.gui_displaystats_checkbox.SetValue(self.config['gui_displaystats'])
-
- self.gui_displaymiscstats_checkbox = wxCheckBox(panel, -1, "Display miscellaneous other statistics")
- self.gui_displaymiscstats_checkbox.SetFont(self.default_font)
- self.gui_displaymiscstats_checkbox.SetValue(self.config['gui_displaymiscstats'])
-
- self.security_checkbox = wxCheckBox(panel, -1, "Don't allow multiple connections from the same IP")
- self.security_checkbox.SetFont(self.default_font)
- self.security_checkbox.SetValue(self.config['security'])
-
- self.autokick_checkbox = wxCheckBox(panel, -1, "Kick/ban clients that send you bad data *")
- self.autokick_checkbox.SetFont(self.default_font)
- self.autokick_checkbox.SetValue(self.config['auto_kick'])
-
- self.buffering_checkbox = wxCheckBox(panel, -1, "Enable read/write buffering *")
- self.buffering_checkbox.SetFont(self.default_font)
- self.buffering_checkbox.SetValue(self.config['buffer_reads'])
-
- self.breakup_checkbox = wxCheckBox(panel, -1, "Break-up seed bitfield to foil ISP manipulation")
- self.breakup_checkbox.SetFont(self.default_font)
- self.breakup_checkbox.SetValue(self.config['breakup_seed_bitfield'])
-
- self.autoflush_checkbox = wxCheckBox(panel, -1, "Flush data to disk every 5 minutes")
- self.autoflush_checkbox.SetFont(self.default_font)
- self.autoflush_checkbox.SetValue(self.config['auto_flush'])
-
- if sys.version_info >= (2,3) and socket.has_ipv6:
- self.ipv6enabled_checkbox = wxCheckBox(panel, -1, "Initiate and receive connections via IPv6 *")
- self.ipv6enabled_checkbox.SetFont(self.default_font)
- self.ipv6enabled_checkbox.SetValue(self.config['ipv6_enabled'])
-
- self.gui_forcegreenonfirewall_checkbox = wxCheckBox(panel, -1,
- "Force icon to display green when firewalled")
- self.gui_forcegreenonfirewall_checkbox.SetFont(self.default_font)
- self.gui_forcegreenonfirewall_checkbox.SetValue(self.config['gui_forcegreenonfirewall'])
-
-
- self.minport_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*8, -1))
- self.minport_data.SetFont(self.default_font)
- self.minport_data.SetRange(1,65535)
- self.minport_data.SetValue(self.config['minport'])
-
- self.maxport_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*8, -1))
- self.maxport_data.SetFont(self.default_font)
- self.maxport_data.SetRange(1,65535)
- self.maxport_data.SetValue(self.config['maxport'])
-
- self.randomport_checkbox = wxCheckBox(panel, -1, "randomize")
- self.randomport_checkbox.SetFont(self.default_font)
- self.randomport_checkbox.SetValue(self.config['random_port'])
-
- self.gui_font_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*5, -1))
- self.gui_font_data.SetFont(self.default_font)
- self.gui_font_data.SetRange(8,16)
- self.gui_font_data.SetValue(self.config['gui_font'])
-
- self.gui_ratesettingsdefault_data=wxChoice(panel, -1, choices = ratesettingslist)
- self.gui_ratesettingsdefault_data.SetFont(self.default_font)
- self.gui_ratesettingsdefault_data.SetStringSelection(self.config['gui_ratesettingsdefault'])
-
- self.maxdownload_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7, -1))
- self.maxdownload_data.SetFont(self.default_font)
- self.maxdownload_data.SetRange(0,5000)
- self.maxdownload_data.SetValue(self.config['max_download_rate'])
-
- self.gui_ratesettingsmode_data=wxRadioBox(panel, -1, 'Rate Settings Mode',
- choices = [ 'none', 'basic', 'full' ] )
- self.gui_ratesettingsmode_data.SetFont(self.default_font)
- self.gui_ratesettingsmode_data.SetStringSelection(self.config['gui_ratesettingsmode'])
-
- if (sys.platform == 'win32'):
- self.win32_taskbar_icon_checkbox = wxCheckBox(panel, -1, "Minimize to system tray")
- self.win32_taskbar_icon_checkbox.SetFont(self.default_font)
- self.win32_taskbar_icon_checkbox.SetValue(self.config['win32_taskbar_icon'])
-
-# self.upnp_checkbox = wxCheckBox(panel, -1, "Enable automatic UPnP port forwarding")
-# self.upnp_checkbox.SetFont(self.default_font)
-# self.upnp_checkbox.SetValue(self.config['upnp_nat_access'])
- self.upnp_data=wxChoice(panel, -1,
- choices = ['disabled', 'type 1 (fast)', 'type 2 (slow)'])
- self.upnp_data.SetFont(self.default_font)
- self.upnp_data.SetSelection(self.config['upnp_nat_access'])
-
- self.gui_default_savedir_ctrl = wxTextCtrl(parent = panel, id = -1,
- value = self.config['gui_default_savedir'],
- size = (26*self.FONT, -1), style = wxTE_PROCESS_TAB)
- self.gui_default_savedir_ctrl.SetFont(self.default_font)
-
- self.gui_savemode_data=wxRadioBox(panel, -1, 'Ask where to save: *',
- choices = [ 'always', 'never', 'auto-resume' ] )
- self.gui_savemode_data.SetFont(self.default_font)
- self.gui_savemode_data.SetSelection(1-self.config['gui_saveas_ask'])
-
- self.checkingcolor_icon = wxEmptyBitmap(16,16)
- self.checkingcolor_iconptr = wxStaticBitmap(panel, -1, self.checkingcolor_icon)
- self.setColorIcon(self.checkingcolor_icon, self.checkingcolor_iconptr, self.checkingcolor)
-
- self.downloadcolor_icon = wxEmptyBitmap(16,16)
- self.downloadcolor_iconptr = wxStaticBitmap(panel, -1, self.downloadcolor_icon)
- self.setColorIcon(self.downloadcolor_icon, self.downloadcolor_iconptr, self.downloadcolor)
-
- self.seedingcolor_icon = wxEmptyBitmap(16,16)
- self.seedingcolor_iconptr = wxStaticBitmap(panel, -1, self.seedingcolor_icon)
- self.setColorIcon(self.seedingcolor_icon, self.downloadcolor_iconptr, self.seedingcolor)
-
- rowsizer = wxFlexGridSizer(cols = 2, hgap = 20)
-
- block12sizer = wxFlexGridSizer(cols = 1, vgap = 7)
-
- block1sizer = wxFlexGridSizer(cols = 1, vgap = 2)
- if (sys.platform == 'win32'):
- block1sizer.Add(self.win32_taskbar_icon_checkbox)
-# block1sizer.Add(self.upnp_checkbox)
- block1sizer.Add(self.gui_stretchwindow_checkbox)
- block1sizer.Add(self.gui_displaystats_checkbox)
- block1sizer.Add(self.gui_displaymiscstats_checkbox)
- block1sizer.Add(self.security_checkbox)
- block1sizer.Add(self.autokick_checkbox)
- block1sizer.Add(self.buffering_checkbox)
- block1sizer.Add(self.breakup_checkbox)
- block1sizer.Add(self.autoflush_checkbox)
- if sys.version_info >= (2,3) and socket.has_ipv6:
- block1sizer.Add(self.ipv6enabled_checkbox)
- block1sizer.Add(self.gui_forcegreenonfirewall_checkbox)
-
- block12sizer.Add(block1sizer)
-
- colorsizer = wxStaticBoxSizer(wxStaticBox(panel, -1, "Gauge Colors:"), wxVERTICAL)
- colorsizer1 = wxFlexGridSizer(cols = 7)
- colorsizer1.Add(StaticText(' Checking: '), 1, wxALIGN_BOTTOM)
- colorsizer1.Add(self.checkingcolor_iconptr, 1, wxALIGN_BOTTOM)
- colorsizer1.Add(StaticText(' Downloading: '), 1, wxALIGN_BOTTOM)
- colorsizer1.Add(self.downloadcolor_iconptr, 1, wxALIGN_BOTTOM)
- colorsizer1.Add(StaticText(' Seeding: '), 1, wxALIGN_BOTTOM)
- colorsizer1.Add(self.seedingcolor_iconptr, 1, wxALIGN_BOTTOM)
- colorsizer1.Add(StaticText(' '))
- minsize = self.checkingcolor_iconptr.GetBestSize()
- minsize.SetHeight(minsize.GetHeight()+5)
- colorsizer1.SetMinSize(minsize)
- colorsizer.Add(colorsizer1)
-
- block12sizer.Add(colorsizer, 1, wxALIGN_LEFT)
-
- rowsizer.Add(block12sizer)
-
- block3sizer = wxFlexGridSizer(cols = 1)
-
- portsettingsSizer = wxStaticBoxSizer(wxStaticBox(panel, -1, "Port Range:*"), wxVERTICAL)
- portsettingsSizer1 = wxGridSizer(cols = 2, vgap = 1)
- portsettingsSizer1.Add(StaticText('From: '), 1, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT)
- portsettingsSizer1.Add(self.minport_data, 1, wxALIGN_BOTTOM)
- portsettingsSizer1.Add(StaticText('To: '), 1, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT)
- portsettingsSizer1.Add(self.maxport_data, 1, wxALIGN_BOTTOM)
- portsettingsSizer.Add(portsettingsSizer1)
- portsettingsSizer.Add(self.randomport_checkbox, 1, wxALIGN_CENTER)
- block3sizer.Add(portsettingsSizer, 1, wxALIGN_CENTER)
- block3sizer.Add(StaticText(' '))
- block3sizer.Add(self.gui_ratesettingsmode_data, 1, wxALIGN_CENTER)
- block3sizer.Add(StaticText(' '))
- ratesettingsSizer = wxFlexGridSizer(cols = 1, vgap = 2)
- ratesettingsSizer.Add(StaticText('Default Rate Setting: *'), 1, wxALIGN_CENTER)
- ratesettingsSizer.Add(self.gui_ratesettingsdefault_data, 1, wxALIGN_CENTER)
- block3sizer.Add(ratesettingsSizer, 1, wxALIGN_CENTER)
- if (sys.platform == 'win32'):
- block3sizer.Add(StaticText(' '))
- upnpSizer = wxFlexGridSizer(cols = 1, vgap = 2)
- upnpSizer.Add(StaticText('UPnP Port Forwarding: *'), 1, wxALIGN_CENTER)
- upnpSizer.Add(self.upnp_data, 1, wxALIGN_CENTER)
- block3sizer.Add(upnpSizer, 1, wxALIGN_CENTER)
-
- rowsizer.Add(block3sizer)
- colsizer.Add(rowsizer)
-
- block4sizer = wxFlexGridSizer(cols = 3, hgap = 15)
- savepathsizer = wxFlexGridSizer(cols = 2, vgap = 1)
- savepathsizer.Add(StaticText('Default Save Path: *'))
- savepathsizer.Add(StaticText(' '))
- savepathsizer.Add(self.gui_default_savedir_ctrl, 1, wxEXPAND)
- savepathButton = wxButton(panel, -1, '...', size = (18,18))
-# savepathButton.SetFont(self.default_font)
- savepathsizer.Add(savepathButton, 0, wxALIGN_CENTER)
- savepathsizer.Add(self.gui_savemode_data, 0, wxALIGN_CENTER)
- block4sizer.Add(savepathsizer, -1, wxALIGN_BOTTOM)
-
- fontsizer = wxFlexGridSizer(cols = 1, vgap = 2)
- fontsizer.Add(StaticText(''))
- fontsizer.Add(StaticText('Font: *'), 1, wxALIGN_CENTER)
- fontsizer.Add(self.gui_font_data, 1, wxALIGN_CENTER)
- block4sizer.Add(fontsizer, 1, wxALIGN_CENTER_VERTICAL)
-
- dratesettingsSizer = wxFlexGridSizer(cols = 1, vgap = 2)
- dratesettingsSizer.Add(StaticText('Default Max'), 1, wxALIGN_CENTER)
- dratesettingsSizer.Add(StaticText('Download Rate'), 1, wxALIGN_CENTER)
- dratesettingsSizer.Add(StaticText('(kB/s): *'), 1, wxALIGN_CENTER)
- dratesettingsSizer.Add(self.maxdownload_data, 1, wxALIGN_CENTER)
- dratesettingsSizer.Add(StaticText('(0 = disabled)'), 1, wxALIGN_CENTER)
-
- block4sizer.Add(dratesettingsSizer, 1, wxALIGN_CENTER_VERTICAL)
-
- colsizer.Add(block4sizer, 0, wxALIGN_CENTER)
-# colsizer.Add(StaticText(' '))
-
- savesizer = wxGridSizer(cols = 4, hgap = 10)
- saveButton = wxButton(panel, -1, 'Save')
-# saveButton.SetFont(self.default_font)
- savesizer.Add(saveButton, 0, wxALIGN_CENTER)
-
- cancelButton = wxButton(panel, -1, 'Cancel')
-# cancelButton.SetFont(self.default_font)
- savesizer.Add(cancelButton, 0, wxALIGN_CENTER)
-
- defaultsButton = wxButton(panel, -1, 'Revert to Defaults')
-# defaultsButton.SetFont(self.default_font)
- savesizer.Add(defaultsButton, 0, wxALIGN_CENTER)
-
- advancedButton = wxButton(panel, -1, 'Advanced...')
-# advancedButton.SetFont(self.default_font)
- savesizer.Add(advancedButton, 0, wxALIGN_CENTER)
- colsizer.Add(savesizer, 1, wxALIGN_CENTER)
-
- resizewarningtext=StaticText('* These settings will not take effect until the next time you start BitTorrent', self.FONT-2)
- colsizer.Add(resizewarningtext, 1, wxALIGN_CENTER)
-
- border = wxBoxSizer(wxHORIZONTAL)
- border.Add(colsizer, 1, wxEXPAND | wxALL, 4)
-
- panel.SetSizer(border)
- panel.SetAutoLayout(True)
-
- self.advancedConfig = {}
-
- def setDefaults(evt, self = self):
- try:
- self.minport_data.SetValue(self.defaults['minport'])
- self.maxport_data.SetValue(self.defaults['maxport'])
- self.randomport_checkbox.SetValue(self.defaults['random_port'])
- self.gui_stretchwindow_checkbox.SetValue(self.defaults['gui_stretchwindow'])
- self.gui_displaystats_checkbox.SetValue(self.defaults['gui_displaystats'])
- self.gui_displaymiscstats_checkbox.SetValue(self.defaults['gui_displaymiscstats'])
- self.security_checkbox.SetValue(self.defaults['security'])
- self.autokick_checkbox.SetValue(self.defaults['auto_kick'])
- self.buffering_checkbox.SetValue(self.defaults['buffer_reads'])
- self.breakup_checkbox.SetValue(self.defaults['breakup_seed_bitfield'])
- self.autoflush_checkbox.SetValue(self.defaults['auto_flush'])
- if sys.version_info >= (2,3) and socket.has_ipv6:
- self.ipv6enabled_checkbox.SetValue(self.defaults['ipv6_enabled'])
- self.gui_forcegreenonfirewall_checkbox.SetValue(self.defaults['gui_forcegreenonfirewall'])
- self.gui_font_data.SetValue(self.defaults['gui_font'])
- self.gui_ratesettingsdefault_data.SetStringSelection(self.defaults['gui_ratesettingsdefault'])
- self.maxdownload_data.SetValue(self.defaults['max_download_rate'])
- self.gui_ratesettingsmode_data.SetStringSelection(self.defaults['gui_ratesettingsmode'])
- self.gui_default_savedir_ctrl.SetValue(self.defaults['gui_default_savedir'])
- self.gui_savemode_data.SetSelection(1-self.defaults['gui_saveas_ask'])
-
- self.checkingcolor = HexToColor(self.defaults['gui_checkingcolor'])
- self.setColorIcon(self.checkingcolor_icon, self.checkingcolor_iconptr, self.checkingcolor)
- self.downloadcolor = HexToColor(self.defaults['gui_downloadcolor'])
- self.setColorIcon(self.downloadcolor_icon, self.downloadcolor_iconptr, self.downloadcolor)
- self.seedingcolor = HexToColor(self.defaults['gui_seedingcolor'])
- self.setColorIcon(self.seedingcolor_icon, self.seedingcolor_iconptr, self.seedingcolor)
-
- if (sys.platform == 'win32'):
- self.win32_taskbar_icon_checkbox.SetValue(self.defaults['win32_taskbar_icon'])
-# self.upnp_checkbox.SetValue(self.defaults['upnp_nat_access'])
- self.upnp_data.SetSelection(self.defaults['upnp_nat_access'])
-
- # reset advanced too
- self.advancedConfig = {}
- for key in ['ip', 'bind', 'min_peers', 'max_initiate', 'display_interval',
- 'alloc_type', 'alloc_rate', 'max_files_open', 'max_connections', 'super_seeder',
- 'ipv6_binds_v4', 'double_check', 'triple_check', 'lock_files', 'lock_while_reading',
- 'expire_cache_data']:
- self.advancedConfig[key] = self.defaults[key]
- self.CloseAdvanced()
- except:
- self.parent.exception()
-
-
- def saveConfigs(evt, self = self):
- try:
- self.config['gui_stretchwindow']=int(self.gui_stretchwindow_checkbox.GetValue())
- self.config['gui_displaystats']=int(self.gui_displaystats_checkbox.GetValue())
- self.config['gui_displaymiscstats']=int(self.gui_displaymiscstats_checkbox.GetValue())
- self.config['security']=int(self.security_checkbox.GetValue())
- self.config['auto_kick']=int(self.autokick_checkbox.GetValue())
- buffering=int(self.buffering_checkbox.GetValue())
- self.config['buffer_reads']=buffering
- if buffering:
- self.config['write_buffer_size']=self.defaults['write_buffer_size']
- else:
- self.config['write_buffer_size']=0
- self.config['breakup_seed_bitfield']=int(self.breakup_checkbox.GetValue())
- if self.autoflush_checkbox.GetValue():
- self.config['auto_flush']=5
- else:
- self.config['auto_flush']=0
- if sys.version_info >= (2,3) and socket.has_ipv6:
- self.config['ipv6_enabled']=int(self.ipv6enabled_checkbox.GetValue())
- self.config['gui_forcegreenonfirewall']=int(self.gui_forcegreenonfirewall_checkbox.GetValue())
- self.config['minport']=self.minport_data.GetValue()
- self.config['maxport']=self.maxport_data.GetValue()
- self.config['random_port']=int(self.randomport_checkbox.GetValue())
- self.config['gui_font']=self.gui_font_data.GetValue()
- self.config['gui_ratesettingsdefault']=self.gui_ratesettingsdefault_data.GetStringSelection()
- self.config['max_download_rate']=self.maxdownload_data.GetValue()
- self.config['gui_ratesettingsmode']=self.gui_ratesettingsmode_data.GetStringSelection()
- self.config['gui_default_savedir']=self.gui_default_savedir_ctrl.GetValue()
- self.config['gui_saveas_ask']=1-self.gui_savemode_data.GetSelection()
- self.config['gui_checkingcolor']=ColorToHex(self.checkingcolor)
- self.config['gui_downloadcolor']=ColorToHex(self.downloadcolor)
- self.config['gui_seedingcolor']=ColorToHex(self.seedingcolor)
-
- if (sys.platform == 'win32'):
- self.config['win32_taskbar_icon']=int(self.win32_taskbar_icon_checkbox.GetValue())
-# self.config['upnp_nat_access']=int(self.upnp_checkbox.GetValue())
- self.config['upnp_nat_access']=self.upnp_data.GetSelection()
-
- if self.advancedConfig:
- for key,val in self.advancedConfig.items():
- self.config[key] = val
-
- self.writeConfigFile()
- self._configReset = True
- self.Close()
- except:
- self.parent.exception()
-
- def cancelConfigs(evt, self = self):
- self.Close()
-
- def savepath_set(evt, self = self):
- try:
- d = self.gui_default_savedir_ctrl.GetValue()
- if d == '':
- d = self.config['last_saved']
- dl = wxDirDialog(self.panel, 'Choose a default directory to save to',
- d, style = wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON)
- if dl.ShowModal() == wxID_OK:
- self.gui_default_savedir_ctrl.SetValue(dl.GetPath())
- except:
- self.parent.exception()
-
- def checkingcoloricon_set(evt, self = self):
- try:
- newcolor = self.getColorFromUser(self.panel,self.checkingcolor)
- self.setColorIcon(self.checkingcolor_icon, self.checkingcolor_iconptr, newcolor)
- self.checkingcolor = newcolor
- except:
- self.parent.exception()
-
- def downloadcoloricon_set(evt, self = self):
- try:
- newcolor = self.getColorFromUser(self.panel,self.downloadcolor)
- self.setColorIcon(self.downloadcolor_icon, self.downloadcolor_iconptr, newcolor)
- self.downloadcolor = newcolor
- except:
- self.parent.exception()
-
- def seedingcoloricon_set(evt, self = self):
- try:
- newcolor = self.getColorFromUser(self.panel,self.seedingcolor)
- self.setColorIcon(self.seedingcolor_icon, self.seedingcolor_iconptr, newcolor)
- self.seedingcolor = newcolor
- except:
- self.parent.exception()
-
- EVT_BUTTON(self.configMenuBox, saveButton.GetId(), saveConfigs)
- EVT_BUTTON(self.configMenuBox, cancelButton.GetId(), cancelConfigs)
- EVT_BUTTON(self.configMenuBox, defaultsButton.GetId(), setDefaults)
- EVT_BUTTON(self.configMenuBox, advancedButton.GetId(), self.advancedMenu)
- EVT_BUTTON(self.configMenuBox, savepathButton.GetId(), savepath_set)
- EVT_LEFT_DOWN(self.checkingcolor_iconptr, checkingcoloricon_set)
- EVT_LEFT_DOWN(self.downloadcolor_iconptr, downloadcoloricon_set)
- EVT_LEFT_DOWN(self.seedingcolor_iconptr, seedingcoloricon_set)
-
- self.configMenuBox.Show ()
- border.Fit(panel)
- self.configMenuBox.Fit()
- except:
- self.parent.exception()
-
-
- def Close(self):
- self.CloseAdvanced()
- if self.configMenuBox is not None:
- try:
- self.configMenuBox.Close ()
- except wxPyDeadObjectError, e:
- pass
- self.configMenuBox = None
-
- def advancedMenu(self, event = None):
- try:
- if not self.advancedConfig:
- for key in ['ip', 'bind', 'min_peers', 'max_initiate', 'display_interval',
- 'alloc_type', 'alloc_rate', 'max_files_open', 'max_connections', 'super_seeder',
- 'ipv6_binds_v4', 'double_check', 'triple_check', 'lock_files', 'lock_while_reading',
- 'expire_cache_data']:
- self.advancedConfig[key] = self.config[key]
-
- if (self.advancedMenuBox is not None):
- try:
- self.advancedMenuBox.Close ()
- except wxPyDeadObjectError, e:
- self.advancedMenuBox = None
-
- self.advancedMenuBox = wxFrame(None, -1, 'BitTorrent Advanced Preferences', size = (1,1),
- style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
- if (sys.platform == 'win32'):
- self.advancedMenuBox.SetIcon(self.icon)
-
- panel = wxPanel(self.advancedMenuBox, -1)
-# self.panel = panel
-
- def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
- x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
- x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
- if color is not None:
- x.SetForegroundColour(color)
- return x
-
- colsizer = wxFlexGridSizer(cols = 1, hgap = 13, vgap = 13)
- warningtext = StaticText('CHANGE THESE SETTINGS AT YOUR OWN RISK', self.FONT+4, True, 'Red')
- colsizer.Add(warningtext, 1, wxALIGN_CENTER)
-
- self.ip_data = wxTextCtrl(parent = panel, id = -1,
- value = self.advancedConfig['ip'],
- size = (self.FONT*13, int(self.FONT*2.2)), style = wxTE_PROCESS_TAB)
- self.ip_data.SetFont(self.default_font)
-
- self.bind_data = wxTextCtrl(parent = panel, id = -1,
- value = self.advancedConfig['bind'],
- size = (self.FONT*13, int(self.FONT*2.2)), style = wxTE_PROCESS_TAB)
- self.bind_data.SetFont(self.default_font)
-
- if sys.version_info >= (2,3) and socket.has_ipv6:
- self.ipv6bindsv4_data=wxChoice(panel, -1,
- choices = ['separate sockets', 'single socket'])
- self.ipv6bindsv4_data.SetFont(self.default_font)
- self.ipv6bindsv4_data.SetSelection(self.advancedConfig['ipv6_binds_v4'])
-
- self.minpeers_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7, -1))
- self.minpeers_data.SetFont(self.default_font)
- self.minpeers_data.SetRange(10,100)
- self.minpeers_data.SetValue(self.advancedConfig['min_peers'])
- # max_initiate = 2*minpeers
-
- self.displayinterval_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7, -1))
- self.displayinterval_data.SetFont(self.default_font)
- self.displayinterval_data.SetRange(100,2000)
- self.displayinterval_data.SetValue(int(self.advancedConfig['display_interval']*1000))
-
- self.alloctype_data=wxChoice(panel, -1,
- choices = ['normal', 'background', 'pre-allocate', 'sparse'])
- self.alloctype_data.SetFont(self.default_font)
- self.alloctype_data.SetStringSelection(self.advancedConfig['alloc_type'])
-
- self.allocrate_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7,-1))
- self.allocrate_data.SetFont(self.default_font)
- self.allocrate_data.SetRange(1,100)
- self.allocrate_data.SetValue(int(self.advancedConfig['alloc_rate']))
-
- self.locking_data=wxChoice(panel, -1,
- choices = ['no locking', 'lock while writing', 'lock always'])
- self.locking_data.SetFont(self.default_font)
- if self.advancedConfig['lock_files']:
- if self.advancedConfig['lock_while_reading']:
- self.locking_data.SetSelection(2)
- else:
- self.locking_data.SetSelection(1)
- else:
- self.locking_data.SetSelection(0)
-
- self.doublecheck_data=wxChoice(panel, -1,
- choices = ['no extra checking', 'double-check', 'triple-check'])
- self.doublecheck_data.SetFont(self.default_font)
- if self.advancedConfig['double_check']:
- if self.advancedConfig['triple_check']:
- self.doublecheck_data.SetSelection(2)
- else:
- self.doublecheck_data.SetSelection(1)
- else:
- self.doublecheck_data.SetSelection(0)
-
- self.maxfilesopen_choices = ['50', '100', '200', 'no limit ']
- self.maxfilesopen_data=wxChoice(panel, -1, choices = self.maxfilesopen_choices)
- self.maxfilesopen_data.SetFont(self.default_font)
- setval = self.advancedConfig['max_files_open']
- if setval == 0:
- setval = 'no limit '
- else:
- setval = str(setval)
- if not setval in self.maxfilesopen_choices:
- setval = self.maxfilesopen_choices[0]
- self.maxfilesopen_data.SetStringSelection(setval)
-
- self.maxconnections_choices = ['no limit ', '20', '30', '40', '50', '60', '100', '200']
- self.maxconnections_data=wxChoice(panel, -1, choices = self.maxconnections_choices)
- self.maxconnections_data.SetFont(self.default_font)
- setval = self.advancedConfig['max_connections']
- if setval == 0:
- setval = 'no limit '
- else:
- setval = str(setval)
- if not setval in self.maxconnections_choices:
- setval = self.maxconnections_choices[0]
- self.maxconnections_data.SetStringSelection(setval)
-
- self.superseeder_data=wxChoice(panel, -1,
- choices = ['normal', 'super-seed'])
- self.superseeder_data.SetFont(self.default_font)
- self.superseeder_data.SetSelection(self.advancedConfig['super_seeder'])
-
- self.expirecache_choices = ['never ', '3', '5', '7', '10', '15', '30', '60', '90']
- self.expirecache_data=wxChoice(panel, -1, choices = self.expirecache_choices)
- setval = self.advancedConfig['expire_cache_data']
- if setval == 0:
- setval = 'never '
- else:
- setval = str(setval)
- if not setval in self.expirecache_choices:
- setval = self.expirecache_choices[0]
- self.expirecache_data.SetFont(self.default_font)
- self.expirecache_data.SetStringSelection(setval)
-
-
- twocolsizer = wxFlexGridSizer(cols = 2, hgap = 20)
- datasizer = wxFlexGridSizer(cols = 2, vgap = 2)
- datasizer.Add(StaticText('Local IP: '), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.ip_data)
- datasizer.Add(StaticText('IP to bind to: '), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.bind_data)
- if sys.version_info >= (2,3) and socket.has_ipv6:
- datasizer.Add(StaticText('IPv6 socket handling: '), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.ipv6bindsv4_data)
- datasizer.Add(StaticText('Minimum number of peers: '), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.minpeers_data)
- datasizer.Add(StaticText('Display interval (ms): '), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.displayinterval_data)
- datasizer.Add(StaticText('Disk allocation type:'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.alloctype_data)
- datasizer.Add(StaticText('Allocation rate (MiB/s):'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.allocrate_data)
- datasizer.Add(StaticText('File locking:'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.locking_data)
- datasizer.Add(StaticText('Extra data checking:'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.doublecheck_data)
- datasizer.Add(StaticText('Max files open:'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.maxfilesopen_data)
- datasizer.Add(StaticText('Max peer connections:'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.maxconnections_data)
- datasizer.Add(StaticText('Default seeding mode:'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.superseeder_data)
- datasizer.Add(StaticText('Expire resume data(days):'), 1, wxALIGN_CENTER_VERTICAL)
- datasizer.Add(self.expirecache_data)
-
- twocolsizer.Add(datasizer)
-
- infosizer = wxFlexGridSizer(cols = 1)
- self.hinttext = StaticText('', self.FONT, False, 'Blue')
- infosizer.Add(self.hinttext, 1, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
- infosizer.SetMinSize((180,100))
- twocolsizer.Add(infosizer, 1, wxEXPAND)
-
- colsizer.Add(twocolsizer)
-
- savesizer = wxGridSizer(cols = 3, hgap = 20)
- okButton = wxButton(panel, -1, 'OK')
-# okButton.SetFont(self.default_font)
- savesizer.Add(okButton, 0, wxALIGN_CENTER)
-
- cancelButton = wxButton(panel, -1, 'Cancel')
-# cancelButton.SetFont(self.default_font)
- savesizer.Add(cancelButton, 0, wxALIGN_CENTER)
-
- defaultsButton = wxButton(panel, -1, 'Revert to Defaults')
-# defaultsButton.SetFont(self.default_font)
- savesizer.Add(defaultsButton, 0, wxALIGN_CENTER)
- colsizer.Add(savesizer, 1, wxALIGN_CENTER)
-
- resizewarningtext=StaticText('None of these settings will take effect until the next time you start BitTorrent', self.FONT-2)
- colsizer.Add(resizewarningtext, 1, wxALIGN_CENTER)
-
- border = wxBoxSizer(wxHORIZONTAL)
- border.Add(colsizer, 1, wxEXPAND | wxALL, 4)
-
- panel.SetSizer(border)
- panel.SetAutoLayout(True)
-
- def setDefaults(evt, self = self):
- try:
- self.ip_data.SetValue(self.defaults['ip'])
- self.bind_data.SetValue(self.defaults['bind'])
- if sys.version_info >= (2,3) and socket.has_ipv6:
- self.ipv6bindsv4_data.SetSelection(self.defaults['ipv6_binds_v4'])
- self.minpeers_data.SetValue(self.defaults['min_peers'])
- self.displayinterval_data.SetValue(int(self.defaults['display_interval']*1000))
- self.alloctype_data.SetStringSelection(self.defaults['alloc_type'])
- self.allocrate_data.SetValue(int(self.defaults['alloc_rate']))
- if self.defaults['lock_files']:
- if self.defaults['lock_while_reading']:
- self.locking_data.SetSelection(2)
- else:
- self.locking_data.SetSelection(1)
- else:
- self.locking_data.SetSelection(0)
- if self.defaults['double_check']:
- if self.defaults['triple_check']:
- self.doublecheck_data.SetSelection(2)
- else:
- self.doublecheck_data.SetSelection(1)
- else:
- self.doublecheck_data.SetSelection(0)
- setval = self.defaults['max_files_open']
- if setval == 0:
- setval = 'no limit '
- else:
- setval = str(setval)
- if not setval in self.maxfilesopen_choices:
- setval = self.maxfilesopen_choices[0]
- self.maxfilesopen_data.SetStringSelection(setval)
- setval = self.defaults['max_connections']
- if setval == 0:
- setval = 'no limit '
- else:
- setval = str(setval)
- if not setval in self.maxconnections_choices:
- setval = self.maxconnections_choices[0]
- self.maxconnections_data.SetStringSelection(setval)
- self.superseeder_data.SetSelection(int(self.defaults['super_seeder']))
- setval = self.defaults['expire_cache_data']
- if setval == 0:
- setval = 'never '
- else:
- setval = str(setval)
- if not setval in self.expirecache_choices:
- setval = self.expirecache_choices[0]
- self.expirecache_data.SetStringSelection(setval)
- except:
- self.parent.exception()
-
- def saveConfigs(evt, self = self):
- try:
- self.advancedConfig['ip'] = self.ip_data.GetValue()
- self.advancedConfig['bind'] = self.bind_data.GetValue()
- if sys.version_info >= (2,3) and socket.has_ipv6:
- self.advancedConfig['ipv6_binds_v4'] = self.ipv6bindsv4_data.GetSelection()
- self.advancedConfig['min_peers'] = self.minpeers_data.GetValue()
- self.advancedConfig['display_interval'] = float(self.displayinterval_data.GetValue())/1000
- self.advancedConfig['alloc_type'] = self.alloctype_data.GetStringSelection()
- self.advancedConfig['alloc_rate'] = float(self.allocrate_data.GetValue())
- self.advancedConfig['lock_files'] = int(self.locking_data.GetSelection() >= 1)
- self.advancedConfig['lock_while_reading'] = int(self.locking_data.GetSelection() > 1)
- self.advancedConfig['double_check'] = int(self.doublecheck_data.GetSelection() >= 1)
- self.advancedConfig['triple_check'] = int(self.doublecheck_data.GetSelection() > 1)
- try:
- self.advancedConfig['max_files_open'] = int(self.maxfilesopen_data.GetStringSelection())
- except: # if it ain't a number, it must be "no limit"
- self.advancedConfig['max_files_open'] = 0
- try:
- self.advancedConfig['max_connections'] = int(self.maxconnections_data.GetStringSelection())
- self.advancedConfig['max_initiate'] = min(
- 2*self.advancedConfig['min_peers'], self.advancedConfig['max_connections'])
- except: # if it ain't a number, it must be "no limit"
- self.advancedConfig['max_connections'] = 0
- self.advancedConfig['max_initiate'] = 2*self.advancedConfig['min_peers']
- self.advancedConfig['super_seeder']=int(self.superseeder_data.GetSelection())
- try:
- self.advancedConfig['expire_cache_data'] = int(self.expirecache_data.GetStringSelection())
- except:
- self.advancedConfig['expire_cache_data'] = 0
- self.advancedMenuBox.Close()
- except:
- self.parent.exception()
-
- def cancelConfigs(evt, self = self):
- self.advancedMenuBox.Close()
-
- def ip_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nThe IP reported to the tracker.\n' +
- 'unless the tracker is on the\n' +
- 'same intranet as this client,\n' +
- 'the tracker will autodetect the\n' +
- "client's IP and ignore this\n" +
- "value.")
-
- def bind_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nThe IP the client will bind to.\n' +
- 'Only useful if your machine is\n' +
- 'directly handling multiple IPs.\n' +
- "If you don't know what this is,\n" +
- "leave it blank.")
-
- def ipv6bindsv4_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nCertain operating systems will\n' +
- 'open IPv4 protocol connections on\n' +
- 'an IPv6 socket; others require you\n' +
- "to open two sockets on the same\n" +
- "port, one IPv4 and one IPv6.")
-
- def minpeers_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nThe minimum number of peers the\n' +
- 'client tries to stay connected\n' +
- 'with. Do not set this higher\n' +
- 'unless you have a very fast\n' +
- "connection and a lot of system\n" +
- "resources.")
-
- def displayinterval_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nHow often to update the\n' +
- 'graphical display, in 1/1000s\n' +
- 'of a second. Setting this too low\n' +
- "will strain your computer's\n" +
- "processor and video access.")
-
- def alloctype_hint(evt, self = self):
- self.hinttext.SetLabel('\n\nHow to allocate disk space.\n' +
- 'normal allocates space as data is\n' +
- 'received, background also adds\n' +
- "space in the background, pre-\n" +
- "allocate reserves up front, and\n" +
- 'sparse is only for filesystems\n' +
- 'that support it by default.')
-
- def allocrate_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nAt what rate to allocate disk\n' +
- 'space when allocating in the\n' +
- 'background. Set this too high on a\n' +
- "slow filesystem and your download\n" +
- "will slow to a crawl.")
-
- def locking_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\n\nFile locking prevents other\n' +
- 'programs (including other instances\n' +
- 'of BitTorrent) from accessing files\n' +
- "you are downloading.")
-
- def doublecheck_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nHow much extra checking to do\n' +
- 'making sure no data is corrupted.\n' +
- 'Double-check mode uses more CPU,\n' +
- "while triple-check mode increases\n" +
- "disk accesses.")
-
- def maxfilesopen_hint(evt, self = self):
- self.hinttext.SetLabel('\n\n\nThe maximum number of files to\n' +
- 'keep open at the same time. Zero\n' +
- 'means no limit. Please note that\n' +
- "if this option is in effect,\n" +
- "files are not guaranteed to be\n" +
- "locked.")
-
- def maxconnections_hint(evt, self = self):
- self.hinttext.SetLabel('\n\nSome operating systems, most\n' +
- 'notably Windows 9x/ME combined\n' +
- 'with certain network drivers,\n' +
- "cannot handle more than a certain\n" +
- "number of open ports. If the\n" +
- "client freezes, try setting this\n" +
- "to 60 or below.")
-
- def superseeder_hint(evt, self = self):
- self.hinttext.SetLabel('\n\nThe "super-seed" method allows\n' +
- 'a single source to more efficiently\n' +
- 'seed a large torrent, but is not\n' +
- "necessary in a well-seeded torrent,\n" +
- "and causes problems with statistics.\n" +
- "Unless you routinely seed torrents\n" +
- "you can enable this by selecting\n" +
- '"SUPER-SEED" for connection type.\n' +
- '(once enabled it does not turn off.)')
-
- def expirecache_hint(evt, self = self):
- self.hinttext.SetLabel('\n\nThe client stores temporary data\n' +
- 'in order to handle downloading only\n' +
- 'specific files from the torrent and\n' +
- "so it can resume downloads more\n" +
- "quickly. This sets how long the\n" +
- "client will keep this data before\n" +
- "deleting it to free disk space.")
-
- EVT_BUTTON(self.advancedMenuBox, okButton.GetId(), saveConfigs)
- EVT_BUTTON(self.advancedMenuBox, cancelButton.GetId(), cancelConfigs)
- EVT_BUTTON(self.advancedMenuBox, defaultsButton.GetId(), setDefaults)
- EVT_ENTER_WINDOW(self.ip_data, ip_hint)
- EVT_ENTER_WINDOW(self.bind_data, bind_hint)
- if sys.version_info >= (2,3) and socket.has_ipv6:
- EVT_ENTER_WINDOW(self.ipv6bindsv4_data, ipv6bindsv4_hint)
- EVT_ENTER_WINDOW(self.minpeers_data, minpeers_hint)
- EVT_ENTER_WINDOW(self.displayinterval_data, displayinterval_hint)
- EVT_ENTER_WINDOW(self.alloctype_data, alloctype_hint)
- EVT_ENTER_WINDOW(self.allocrate_data, allocrate_hint)
- EVT_ENTER_WINDOW(self.locking_data, locking_hint)
- EVT_ENTER_WINDOW(self.doublecheck_data, doublecheck_hint)
- EVT_ENTER_WINDOW(self.maxfilesopen_data, maxfilesopen_hint)
- EVT_ENTER_WINDOW(self.maxconnections_data, maxconnections_hint)
- EVT_ENTER_WINDOW(self.superseeder_data, superseeder_hint)
- EVT_ENTER_WINDOW(self.expirecache_data, expirecache_hint)
-
- self.advancedMenuBox.Show ()
- border.Fit(panel)
- self.advancedMenuBox.Fit()
- except:
- self.parent.exception()
-
-
- def CloseAdvanced(self):
- if self.advancedMenuBox is not None:
- try:
- self.advancedMenuBox.Close()
- except wxPyDeadObjectError, e:
- self.advancedMenuBox = None
-
+++ /dev/null
-connChoices=(
- {'name':'automatic',
- 'rate':{'min':0, 'max':5000, 'def': 0},
- 'conn':{'min':0, 'max':100, 'def': 0},
- 'automatic':1},
- {'name':'unlimited',
- 'rate':{'min':0, 'max':5000, 'def': 0, 'div': 50},
- 'conn':{'min':4, 'max':100, 'def': 4}},
- {'name':'dialup/isdn',
- 'rate':{'min':3, 'max': 8, 'def': 5},
- 'conn':{'min':2, 'max': 3, 'def': 2},
- 'initiate': 12},
- {'name':'dsl/cable slow',
- 'rate':{'min':10, 'max': 48, 'def': 13},
- 'conn':{'min':4, 'max': 20, 'def': 4}},
- {'name':'dsl/cable fast',
- 'rate':{'min':20, 'max': 100, 'def': 40},
- 'conn':{'min':4, 'max': 30, 'def': 6}},
- {'name':'T1',
- 'rate':{'min':100, 'max': 300, 'def':150},
- 'conn':{'min':4, 'max': 40, 'def':10}},
- {'name':'T3+',
- 'rate':{'min':400, 'max':2000, 'def':500},
- 'conn':{'min':4, 'max':100, 'def':20}},
- {'name':'seeder',
- 'rate':{'min':0, 'max':5000, 'def':0, 'div': 50},
- 'conn':{'min':1, 'max':100, 'def':1}},
- {'name':'SUPER-SEED', 'super-seed':1}
- )
-
-connChoiceList = map(lambda x:x['name'], connChoices)
+++ /dev/null
-# Generated from bt_MakeCreateIcons - 05/10/04 22:15:33
-# T-0.3.0 (BitTornado)
-
-from binascii import a2b_base64
-from zlib import decompress
-from os.path import join
-
-icons = {
- "icon_bt.ico":
- "eJyt1K+OFEEQx/FaQTh5GDRZhSQpiUHwCrxCBYXFrjyJLXeXEARPsZqUPMm+" +
- "AlmP+PGtngoLDji69zMz2zt/qqtr1mxHv7621d4+MnvK/jl66Bl2drV+e7Wz" +
- "S/v12A7rY4fDtuvOwfF4tOPXo52/fLLz+WwpWd6nqRXHKXux39sTrtnjNd7g" +
- "PW7wGSd860f880kffjvJ2QYS1Zcw4AjcoaA5yRFIFDQXOgKJguZmjkCioB4T" +
- "Y2CqxpTXA7sHEgVNEC8RSBQ0gfk7xtknCupgk3EEEgXlNgFHIFHQTMoRSBQ0" +
- "E+1ouicKmsk7AomCJiGOQKKgSZIjkChoEucIJAqaZDoCiYImwb4iydULmqQ7" +
- "AomC1kLcEQ/jSBQ0i+MIJAqaBXMEElVdi9siOgKJgmZhfWWlVjTddXW/FtsR" +
- "SBQ0BeAIJAqaonAEEgVNoTgCiYKmeByBREHaqiVWRtSRrAJzBBIFTdE5AomC" +
- "phBPpxPP57dVkDfrTl063nUVnWe383fZx9tb3uN+o7U+BLDtuvcQm8d/27Y/" +
- "jO3o5/ay+YPv/+f6y30e1OyB7QcsGWFj",
- "icon_done.ico":
- "eJyt1K2OVEEQhuEaQbJyMWgyCklSEoPgFvYWKigsduRKbLndhCC4itGk5Erm" +
- "Fsh4xMdbfSoMOGDpnuf89Jyf6uqaMdvRr69ttbdPzJ6xf4Eeeo6dXa3vXu/s" +
- "0n49tsP62OGw7bpzcDwe7fj1aOcvn+x8PltKlg9pasVxyl7u9/aUe/Z4gxu8" +
- "xy0+44Rv/Yp/vujDbxc520Ci+hYGHIF7FDQXOQKJguZGRyBR0DzMEUgU1GNi" +
- "DEzVmPJ6YfdAoqAJ4hUCiYImMH/HOPtEQR1sMo5AoqDcJuAIJAqaSTkCiYJm" +
- "oh1N90RBM3lHIFHQJMQRSBQ0SXIEEgVN4hyBREGTTEcgUdAk2FckuXpBk3RH" +
- "IFHQWoh74mEciYJmcRyBREGzYI5AoqprcVtERyBR0Cysr6zUiqa7rh7WYjsC" +
- "iYKmAByBREFTFI5AoqApFEcgUdAUjyOQKEhbtcTKiDqSVWCOQKKgKTpHIFHQ" +
- "FOLpdOL9fLcK8nY9qUvHu66i8+x2/i77eHfH77h/0VofAth23Xuoz/+2bX8Y" +
- "29HP7WXzB+f/5/7Lcx7V7JHtB9dPG3I=",
- "black.ico":
- "eJzt1zsOgkAYReFLLCztjJ2UlpLY485kOS7DpbgESwqTcQZDghjxZwAfyfl0" +
- "LIieGzUWSom/pan840rHnbSUtPHHX9Je9+tAh2ybNe8TZZ/vk8ajJ4zl6JVJ" +
- "+xFx+0R03Djx1/2B8bcT9L/bt0+4Wq+4se8e/VTfMvGqb4n3nYiIGz+lvt9s" +
- "9EpE2T4xJN4xNFYWU6t+JWXuXDFzTom7SodSyi/S+iwtwjlJ80KaNY/C34rW" +
- "aT8nvK5uhF7ohn7Yqfb87kffLAAAAAAAAAAAAAAAAAAAGMUNy7dADg==",
- "blue.ico":
- "eJzt10EOwUAYhuGv6cLSTux06QD2dTM9jmM4iiNYdiEZ81cIFTWddtDkfbQW" +
- "De8XogtS5h9FIf+81H4jLSSt/ekvaavrdaCDez4SZV+PpPHoicBy9ErSfkQ8" +
- "fCI6Hjgx6f7A+McJ+r/t95i46xMP7bf8Uz9o4k0/XMT338voP5shK0MkjXcM" +
- "YSqam6Qunatyf7Nk7iztaqk8SaujNLfzIM0qKX88ZX8rWmf7Nfa+W8N61rW+" +
- "7TR7fverHxYAAAAAAAAAAAAAAAAAAIziApVZ444=",
- "green.ico":
- "eJzt1zEOgjAAheFHGBzdjJuMHsAdbybxNB7Do3gERwaT2mJIBCOWlqok/yc4" +
- "EP1fNDIoZfZRFLLPa5120krS1p72kvZ6XAeGHLtHouzrkTQePOFZDl5J2g+I" +
- "+08Exz0nZt2PjH+coP/bvveEaY2L+/VN13/1PSbe9v0FfP+jTP6ziVmJkTQ+" +
- "MISZaO6SujSmyu3dkpmbdKil8iptLtLSnWdpUUn58yn3t6J39l/j3tc2XM91" +
- "Xd/tNHt296sfFgAAAAAAAAAAAAAAAAAATOIOVLEoDg==",
- "red.ico":
- "eJzt10EOwUAYhuGv6cLSTux06QD2dTOO4xiO4giWXUjG/BVCRTuddtDkfbQW" +
- "De8XogtS5h9FIf+81GEjLSSt/ekvaavbdaCVez0SZd+PpPHoicBy9ErSfkQ8" +
- "fCI6Hjgx6f7AeOcE/d/2QyceesaD+g1/1u+e+NwPF/H99zL6z2bIyhBJ4y1D" +
- "mIb6LqlK5/a5v1syd5F2lVSepdVJmtt5lGZ7KX8+ZX8rGmfzNfa+e8N61rW+" +
- "7dR7fverHxYAAAAAAAAAAAAAAAAAAIziCpgs444=",
- "white.ico":
- "eJzt1zsOgkAYReFLKCztjJ2ULsAed6bLcRnuwYTaJVhSmIwzGBLEiD8D+EjO" +
- "p2NB9NyosVBK/C3L5B+XOmykhaS1P/6StrpfBzoUp6J5nyj7fJ80Hj1hLEev" +
- "TNqPiNsnouPGib/uD4y/naD/3b59wtV6xY199+in+paJV31LvO9ERNz4KfX9" +
- "ZqNXIsr2iSHxjqGxspha9Sspc+f2qXNK3FXalVJ+kVZnaR7OUZrtpbR5FP5W" +
- "tE77OeF1dSP0Qjf0w06153c/+mYBAAAAAAAAAAAAAAAAAMAobj//I7s=",
- "yellow.ico":
- "eJzt1zsOgkAYReFLKCztjJ2ULsAedybLcRkuxSVYUpiM82M0ihGHgVFJzidY" +
- "ED03vgqlzN+KQv5+qf1GWkha+9Nf0lbX60AX556ORNnXI2k8eiKwHL2StB8R" +
- "D5+IjgdOTLo/MP5xgv5v+8ETd/3iYf2W/+oHTLzth4t4/3sZ/WszZGWIpPGO" +
- "IUxE8yupS+eq3H9smTtLu1oqT9LqKM3tPEizSsofT9nfitbZfow979awnnWt" +
- "bzvNnt/96osFAAAAAAAAAAAAAAAAAACjuABhjmIs",
- "black1.ico":
- "eJzt0zEOgkAUANEhFpZSGTstTWzkVt5Cj8ZROAIHMNGPWBCFDYgxMZkHn2Iz" +
- "G5YCyOLKc+K54XSANbCPiSV2tOt/qjgW3XtSnN41FH/Qv29Jx/P7qefp7W8P" +
- "4z85HQ+9JRG/7BpTft31DPUKyiVcFjEZzQ/TTtdzrWnKmCr6evv780qSJEmS" +
- "JEmSJEmSJEmSpPnunVFDcA==",
- "green1.ico":
- "eJzt0zEKwkAQRuEXLCyTSuy0DHgxb6F4shzFI+QAgpkkFoombowIwvt2Z4vh" +
- "X5gtFrJYRUGca/Y7WAFlVLTY0vf/1elxTwqP3xoKf5B/vjIenp+fOs+r/LWT" +
- "/uQ34aGpUqQnv+1ygDqHagnHRVRG+2H6unfrtZkq6hz5evP7eSVJkiRJkiRJ" +
- "kiRJkiRJ0nwNoWQ+AA==",
- "yellow1.ico":
- "eJzt0zEKwkAQRuEXLCxNJXZaCl7MW8Sj5SgeIQcQ4oS1UDTJxkhAeN/ubDH8" +
- "C7PFQhGrLIlzx/kEW+AYFS0OpP6/atuXPSk8fKsv/EX+/cpweH5+6jyf8kn+" +
- "k0fCfVPlyE/+2q2CZgP1Gi6rqILuw6R69uh1mTrqGvlmv/y8kiRJkiRJkiRJ" +
- "kiRJkiRpvjsp9L8k",
- "alloc.gif":
- "eJxz93SzsEw0YRBh+M4ABi0MS3ue///P8H8UjIIRBhR/sjAyMDAx6IAyAihP" +
- "MHAcYWDlkPHYsOBgM4ewVsyJDQsPNzEoebF8CHjo0smjH3dmRsDjI33C7Dw3" +
- "MiYuOtjNyDShRSNwyemJguJJKhaGS32nGka61Vg2NJyYKRd+bY+nwtMzjbqV" +
- "Qh84gxMCJgnlL4vJuqJyaa5NfFLNLsNVV2a7syacfVWkHd4bv7RN1ltM7ejm" +
- "tMtNZ19Oyb02p8C3aqr3dr2GbXl/7fZyOej5rW653WZ7MzzHZV+v7O2/EZM+" +
- "Pt45kbX6ScWHNWfOilo3n5thucXv8org1XF3DRQYrAEWiVY3"
-}
-
-def GetIcons():
- return icons.keys()
-
-def CreateIcon(icon, savedir):
- try:
- f = open(join(savedir,icon),"wb")
- f.write(decompress(a2b_base64(icons[icon])))
- success = 1
- except:
- success = 0
- try:
- f.close()
- except:
- pass
- return success
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from clock import clock
-
-class Measure:
- def __init__(self, max_rate_period, fudge = 1):
- self.max_rate_period = max_rate_period
- self.ratesince = clock() - fudge
- self.last = self.ratesince
- self.rate = 0.0
- self.total = 0l
-
- def update_rate(self, amount):
- self.total += amount
- t = clock()
- self.rate = (self.rate * (self.last - self.ratesince) +
- amount) / (t - self.ratesince + 0.0001)
- self.last = t
- if self.ratesince < t - self.max_rate_period:
- self.ratesince = t - self.max_rate_period
-
- def get_rate(self):
- self.update_rate(0)
- return self.rate
-
- def get_rate_noupdate(self):
- return self.rate
-
- def time_until_rate(self, newrate):
- if self.rate <= newrate:
- return 0
- t = clock() - self.ratesince
- return ((self.rate * t) / newrate) - t
-
- def get_total(self):
- return self.total
\ No newline at end of file
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from cStringIO import StringIO
-from sys import stdout
-import time
-from clock import clock
-from gzip import GzipFile
-try:
- True
-except:
- True = 1
- False = 0
-
-DEBUG = False
-
-weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
-
-months = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
-
-class HTTPConnection:
- def __init__(self, handler, connection):
- self.handler = handler
- self.connection = connection
- self.buf = ''
- self.closed = False
- self.done = False
- self.donereading = False
- self.next_func = self.read_type
-
- def get_ip(self):
- return self.connection.get_ip()
-
- def data_came_in(self, data):
- if self.donereading or self.next_func is None:
- return True
- self.buf += data
- while True:
- try:
- i = self.buf.index('\n')
- except ValueError:
- return True
- val = self.buf[:i]
- self.buf = self.buf[i+1:]
- self.next_func = self.next_func(val)
- if self.donereading:
- return True
- if self.next_func is None or self.closed:
- return False
-
- def read_type(self, data):
- self.header = data.strip()
- words = data.split()
- if len(words) == 3:
- self.command, self.path, garbage = words
- self.pre1 = False
- elif len(words) == 2:
- self.command, self.path = words
- self.pre1 = True
- if self.command != 'GET':
- return None
- else:
- return None
- if self.command not in ('HEAD', 'GET'):
- return None
- self.headers = {}
- return self.read_header
-
- def read_header(self, data):
- data = data.strip()
- if data == '':
- self.donereading = True
- if self.headers.get('accept-encoding','').find('gzip') > -1:
- self.encoding = 'gzip'
- else:
- self.encoding = 'identity'
- r = self.handler.getfunc(self, self.path, self.headers)
- if r is not None:
- self.answer(r)
- return None
- try:
- i = data.index(':')
- except ValueError:
- return None
- self.headers[data[:i].strip().lower()] = data[i+1:].strip()
- if DEBUG:
- print data[:i].strip() + ": " + data[i+1:].strip()
- return self.read_header
-
- def answer(self, (responsecode, responsestring, headers, data)):
- if self.closed:
- return
- if self.encoding == 'gzip':
- compressed = StringIO()
- gz = GzipFile(fileobj = compressed, mode = 'wb', compresslevel = 9)
- gz.write(data)
- gz.close()
- cdata = compressed.getvalue()
- if len(cdata) >= len(data):
- self.encoding = 'identity'
- else:
- if DEBUG:
- print "Compressed: %i Uncompressed: %i\n" % (len(cdata),len(data))
- data = cdata
- headers['Content-Encoding'] = 'gzip'
-
- # i'm abusing the identd field here, but this should be ok
- if self.encoding == 'identity':
- ident = '-'
- else:
- ident = self.encoding
- self.handler.log( self.connection.get_ip(), ident, '-',
- self.header, responsecode, len(data),
- self.headers.get('referer','-'),
- self.headers.get('user-agent','-') )
- self.done = True
- r = StringIO()
- r.write('HTTP/1.0 ' + str(responsecode) + ' ' +
- responsestring + '\r\n')
- if not self.pre1:
- headers['Content-Length'] = len(data)
- for key, value in headers.items():
- r.write(key + ': ' + str(value) + '\r\n')
- r.write('\r\n')
- if self.command != 'HEAD':
- r.write(data)
- self.connection.write(r.getvalue())
- if self.connection.is_flushed():
- self.connection.shutdown(1)
-
-class HTTPHandler:
- def __init__(self, getfunc, minflush):
- self.connections = {}
- self.getfunc = getfunc
- self.minflush = minflush
- self.lastflush = clock()
-
- def external_connection_made(self, connection):
- self.connections[connection] = HTTPConnection(self, connection)
-
- def connection_flushed(self, connection):
- if self.connections[connection].done:
- connection.shutdown(1)
-
- def connection_lost(self, connection):
- ec = self.connections[connection]
- ec.closed = True
- del ec.connection
- del ec.next_func
- del self.connections[connection]
-
- def data_came_in(self, connection, data):
- c = self.connections[connection]
- if not c.data_came_in(data) and not c.closed:
- c.connection.shutdown(1)
-
- def log(self, ip, ident, username, header,
- responsecode, length, referrer, useragent):
- year, month, day, hour, minute, second, a, b, c = time.localtime(time.time())
- print '%s %s %s [%02d/%3s/%04d:%02d:%02d:%02d] "%s" %i %i "%s" "%s"' % (
- ip, ident, username, day, months[month], year, hour,
- minute, second, header, responsecode, length, referrer, useragent)
- t = clock()
- if t - self.lastflush > self.minflush:
- self.lastflush = t
- stdout.flush()
+++ /dev/null
-# edit this file to enable/disable Psyco
-# psyco = 1 -- enabled
-# psyco = 0 -- disabled
-
-psyco = 0
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from traceback import print_exc
-from binascii import b2a_hex
-from clock import clock
-from CurrentRateMeasure import Measure
-from cStringIO import StringIO
-from math import sqrt
-
-try:
- True
-except:
- True = 1
- False = 0
-try:
- sum([1])
-except:
- sum = lambda a: reduce(lambda x,y: x+y, a, 0)
-
-DEBUG = False
-
-MAX_RATE_PERIOD = 20.0
-MAX_RATE = 10e10
-PING_BOUNDARY = 1.2
-PING_SAMPLES = 7
-PING_DISCARDS = 1
-PING_THRESHHOLD = 5
-PING_DELAY = 5 # cycles 'til first upward adjustment
-PING_DELAY_NEXT = 2 # 'til next
-ADJUST_UP = 1.05
-ADJUST_DOWN = 0.95
-UP_DELAY_FIRST = 5
-UP_DELAY_NEXT = 2
-SLOTS_STARTING = 6
-SLOTS_FACTOR = 1.66/1000
-
-class RateLimiter:
- def __init__(self, sched, unitsize, slotsfunc = lambda x: None):
- self.sched = sched
- self.last = None
- self.unitsize = unitsize
- self.slotsfunc = slotsfunc
- self.measure = Measure(MAX_RATE_PERIOD)
- self.autoadjust = False
- self.upload_rate = MAX_RATE * 1000
- self.slots = SLOTS_STARTING # garbage if not automatic
-
- def set_upload_rate(self, rate):
- # rate = -1 # test automatic
- if rate < 0:
- if self.autoadjust:
- return
- self.autoadjust = True
- self.autoadjustup = 0
- self.pings = []
- rate = MAX_RATE
- self.slots = SLOTS_STARTING
- self.slotsfunc(self.slots)
- else:
- self.autoadjust = False
- if not rate:
- rate = MAX_RATE
- self.upload_rate = rate * 1000
- self.lasttime = clock()
- self.bytes_sent = 0
-
- def queue(self, conn):
- assert conn.next_upload is None
- if self.last is None:
- self.last = conn
- conn.next_upload = conn
- self.try_send(True)
- else:
- conn.next_upload = self.last.next_upload
- self.last.next_upload = conn
- self.last = conn
-
- def try_send(self, check_time = False):
- t = clock()
- self.bytes_sent -= (t - self.lasttime) * self.upload_rate
- self.lasttime = t
- if check_time:
- self.bytes_sent = max(self.bytes_sent, 0)
- cur = self.last.next_upload
- while self.bytes_sent <= 0:
- bytes = cur.send_partial(self.unitsize)
- self.bytes_sent += bytes
- self.measure.update_rate(bytes)
- if bytes == 0 or cur.backlogged():
- if self.last is cur:
- self.last = None
- cur.next_upload = None
- break
- else:
- self.last.next_upload = cur.next_upload
- cur.next_upload = None
- cur = self.last.next_upload
- else:
- self.last = cur
- cur = cur.next_upload
- else:
- self.sched(self.try_send, self.bytes_sent / self.upload_rate)
-
- def adjust_sent(self, bytes):
- self.bytes_sent = min(self.bytes_sent+bytes, self.upload_rate*3)
- self.measure.update_rate(bytes)
-
-
- def ping(self, delay):
- if DEBUG:
- print delay
- if not self.autoadjust:
- return
- self.pings.append(delay > PING_BOUNDARY)
- if len(self.pings) < PING_SAMPLES+PING_DISCARDS:
- return
- if DEBUG:
- print 'cycle'
- pings = sum(self.pings[PING_DISCARDS:])
- del self.pings[:]
- if pings >= PING_THRESHHOLD: # assume flooded
- if self.upload_rate == MAX_RATE:
- self.upload_rate = self.measure.get_rate()*ADJUST_DOWN
- else:
- self.upload_rate = min(self.upload_rate,
- self.measure.get_rate()*1.1)
- self.upload_rate = max(int(self.upload_rate*ADJUST_DOWN),2)
- self.slots = int(sqrt(self.upload_rate*SLOTS_FACTOR))
- self.slotsfunc(self.slots)
- if DEBUG:
- print 'adjust down to '+str(self.upload_rate)
- self.lasttime = clock()
- self.bytes_sent = 0
- self.autoadjustup = UP_DELAY_FIRST
- else: # not flooded
- if self.upload_rate == MAX_RATE:
- return
- self.autoadjustup -= 1
- if self.autoadjustup:
- return
- self.upload_rate = int(self.upload_rate*ADJUST_UP)
- self.slots = int(sqrt(self.upload_rate*SLOTS_FACTOR))
- self.slotsfunc(self.slots)
- if DEBUG:
- print 'adjust up to '+str(self.upload_rate)
- self.lasttime = clock()
- self.bytes_sent = 0
- self.autoadjustup = UP_DELAY_NEXT
-
-
-
-
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from clock import clock
-try:
- True
-except:
- True = 1
- False = 0
-
-FACTOR = 0.999
-
-class RateMeasure:
- def __init__(self):
- self.last = None
- self.time = 1.0
- self.got = 0.0
- self.remaining = None
- self.broke = False
- self.got_anything = False
- self.last_checked = None
- self.rate = 0
- self.lastten = False
-
- def data_came_in(self, amount):
- if not self.got_anything:
- self.got_anything = True
- self.last = clock()
- return
- self.update(amount)
-
- def data_rejected(self, amount):
- pass
-
- def get_time_left(self, left):
- t = clock()
- if not self.got_anything:
- return None
- if t - self.last > 15:
- self.update(0)
- try:
- remaining = left/self.rate
- if not self.lastten and remaining <= 10:
- self.lastten = True
- if self.lastten:
- return remaining
- delta = max(remaining/20,2)
- if self.remaining is None:
- self.remaining = remaining
- elif abs(self.remaining-remaining) > delta:
- self.remaining = remaining
- else:
- self.remaining -= t - self.last_checked
- except ZeroDivisionError:
- self.remaining = None
- if self.remaining is not None and self.remaining < 0.1:
- self.remaining = 0.1
- self.last_checked = t
- return self.remaining
-
- def update(self, amount):
- t = clock()
- t1 = int(t)
- l1 = int(self.last)
- for i in xrange(l1,t1):
- self.time *= FACTOR
- self.got *= FACTOR
- self.got += amount
- if t - self.last < 20:
- self.time += t - self.last
- self.last = t
- try:
- self.rate = self.got / self.time
- except ZeroDivisionError:
- pass
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from bisect import insort
-from SocketHandler import SocketHandler, UPnP_ERROR
-import socket
-from cStringIO import StringIO
-from traceback import print_exc
-from select import error
-from threading import Thread, Event
-from time import sleep
-from clock import clock
-import sys
-try:
- True
-except:
- True = 1
- False = 0
-
-
-def autodetect_ipv6():
- try:
- assert sys.version_info >= (2,3)
- assert socket.has_ipv6
- socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- except:
- return 0
- return 1
-
-def autodetect_socket_style():
- if sys.platform.find('linux') < 0:
- return 1
- else:
- try:
- f = open('/proc/sys/net/ipv6/bindv6only','r')
- dual_socket_style = int(f.read())
- f.close()
- return int(not dual_socket_style)
- except:
- return 0
-
-
-READSIZE = 100000
-
-class RawServer:
- def __init__(self, doneflag, timeout_check_interval, timeout, noisy = True,
- ipv6_enable = True, failfunc = lambda x: None, errorfunc = None,
- sockethandler = None, excflag = Event()):
- self.timeout_check_interval = timeout_check_interval
- self.timeout = timeout
- self.servers = {}
- self.single_sockets = {}
- self.dead_from_write = []
- self.doneflag = doneflag
- self.noisy = noisy
- self.failfunc = failfunc
- self.errorfunc = errorfunc
- self.exccount = 0
- self.funcs = []
- self.externally_added = []
- self.finished = Event()
- self.tasks_to_kill = []
- self.excflag = excflag
-
- if sockethandler is None:
- sockethandler = SocketHandler(timeout, ipv6_enable, READSIZE)
- self.sockethandler = sockethandler
- self.add_task(self.scan_for_timeouts, timeout_check_interval)
-
- def get_exception_flag(self):
- return self.excflag
-
- def _add_task(self, func, delay, id = None):
- assert float(delay) >= 0
- insort(self.funcs, (clock() + delay, func, id))
-
- def add_task(self, func, delay = 0, id = None):
- assert float(delay) >= 0
- self.externally_added.append((func, delay, id))
-
- def scan_for_timeouts(self):
- self.add_task(self.scan_for_timeouts, self.timeout_check_interval)
- self.sockethandler.scan_for_timeouts()
-
- def bind(self, port, bind = '', reuse = False,
- ipv6_socket_style = 1, upnp = False):
- self.sockethandler.bind(port, bind, reuse, ipv6_socket_style, upnp)
-
- def find_and_bind(self, minport, maxport, bind = '', reuse = False,
- ipv6_socket_style = 1, upnp = 0, randomizer = False):
- return self.sockethandler.find_and_bind(minport, maxport, bind, reuse,
- ipv6_socket_style, upnp, randomizer)
-
- def start_connection_raw(self, dns, socktype, handler = None):
- return self.sockethandler.start_connection_raw(dns, socktype, handler)
-
- def start_connection(self, dns, handler = None, randomize = False):
- return self.sockethandler.start_connection(dns, handler, randomize)
-
- def get_stats(self):
- return self.sockethandler.get_stats()
-
- def pop_external(self):
- while self.externally_added:
- (a, b, c) = self.externally_added.pop(0)
- self._add_task(a, b, c)
-
-
- def listen_forever(self, handler):
- self.sockethandler.set_handler(handler)
- try:
- while not self.doneflag.isSet():
- try:
- self.pop_external()
- self._kill_tasks()
- if self.funcs:
- period = self.funcs[0][0] + 0.001 - clock()
- else:
- period = 2 ** 30
- if period < 0:
- period = 0
- events = self.sockethandler.do_poll(period)
- if self.doneflag.isSet():
- return
- while self.funcs and self.funcs[0][0] <= clock():
- garbage1, func, id = self.funcs.pop(0)
- if id in self.tasks_to_kill:
- pass
- try:
-# print func.func_name
- func()
- except (SystemError, MemoryError), e:
- self.failfunc(str(e))
- return
- except KeyboardInterrupt:
-# self.exception(True)
- return
- except:
- if self.noisy:
- self.exception()
- self.sockethandler.close_dead()
- self.sockethandler.handle_events(events)
- if self.doneflag.isSet():
- return
- self.sockethandler.close_dead()
- except (SystemError, MemoryError), e:
- self.failfunc(str(e))
- return
- except error:
- if self.doneflag.isSet():
- return
- except KeyboardInterrupt:
-# self.exception(True)
- return
- except:
- self.exception()
- if self.exccount > 10:
- return
- finally:
-# self.sockethandler.shutdown()
- self.finished.set()
-
- def is_finished(self):
- return self.finished.isSet()
-
- def wait_until_finished(self):
- self.finished.wait()
-
- def _kill_tasks(self):
- if self.tasks_to_kill:
- new_funcs = []
- for (t, func, id) in self.funcs:
- if id not in self.tasks_to_kill:
- new_funcs.append((t, func, id))
- self.funcs = new_funcs
- self.tasks_to_kill = []
-
- def kill_tasks(self, id):
- self.tasks_to_kill.append(id)
-
- def exception(self, kbint = False):
- if not kbint:
- self.excflag.set()
- self.exccount += 1
- if self.errorfunc is None:
- print_exc()
- else:
- data = StringIO()
- print_exc(file = data)
-# print data.getvalue() # report exception here too
- if not kbint: # don't report here if it's a keyboard interrupt
- self.errorfunc(data.getvalue())
-
- def shutdown(self):
- self.sockethandler.shutdown()
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from cStringIO import StringIO
-#from RawServer import RawServer
-try:
- True
-except:
- True = 1
- False = 0
-
-from BT1.Encrypter import protocol_name
-
-default_task_id = []
-
-class SingleRawServer:
- def __init__(self, info_hash, multihandler, doneflag, protocol):
- self.info_hash = info_hash
- self.doneflag = doneflag
- self.protocol = protocol
- self.multihandler = multihandler
- self.rawserver = multihandler.rawserver
- self.finished = False
- self.running = False
- self.handler = None
- self.taskqueue = []
-
- def shutdown(self):
- if not self.finished:
- self.multihandler.shutdown_torrent(self.info_hash)
-
- def _shutdown(self):
- if not self.finished:
- self.finished = True
- self.running = False
- self.rawserver.kill_tasks(self.info_hash)
- if self.handler:
- self.handler.close_all()
-
- def _external_connection_made(self, c, options, already_read):
- if self.running:
- c.set_handler(self.handler)
- self.handler.externally_handshaked_connection_made(
- c, options, already_read)
-
- ### RawServer functions ###
-
- def add_task(self, func, delay=0, id = default_task_id):
- if id is default_task_id:
- id = self.info_hash
- if not self.finished:
- self.rawserver.add_task(func, delay, id)
-
-# def bind(self, port, bind = '', reuse = False):
-# pass # not handled here
-
- def start_connection(self, dns, handler = None):
- if not handler:
- handler = self.handler
- c = self.rawserver.start_connection(dns, handler)
- return c
-
-# def listen_forever(self, handler):
-# pass # don't call with this
-
- def start_listening(self, handler):
- self.handler = handler
- self.running = True
- return self.shutdown # obviously, doesn't listen forever
-
- def is_finished(self):
- return self.finished
-
- def get_exception_flag(self):
- return self.rawserver.get_exception_flag()
-
-
-class NewSocketHandler: # hand a new socket off where it belongs
- def __init__(self, multihandler, connection):
- self.multihandler = multihandler
- self.connection = connection
- connection.set_handler(self)
- self.closed = False
- self.buffer = StringIO()
- self.complete = False
- self.next_len, self.next_func = 1, self.read_header_len
- self.multihandler.rawserver.add_task(self._auto_close, 15)
-
- def _auto_close(self):
- if not self.complete:
- self.close()
-
- def close(self):
- if not self.closed:
- self.connection.close()
- self.closed = True
-
-
-# header format:
-# connection.write(chr(len(protocol_name)) + protocol_name +
-# (chr(0) * 8) + self.encrypter.download_id + self.encrypter.my_id)
-
- # copied from Encrypter and modified
-
- def read_header_len(self, s):
- l = ord(s)
- return l, self.read_header
-
- def read_header(self, s):
- self.protocol = s
- return 8, self.read_reserved
-
- def read_reserved(self, s):
- self.options = s
- return 20, self.read_download_id
-
- def read_download_id(self, s):
- if self.multihandler.singlerawservers.has_key(s):
- if self.multihandler.singlerawservers[s].protocol == self.protocol:
- return True
- return None
-
- def read_dead(self, s):
- return None
-
- def data_came_in(self, garbage, s):
- while True:
- if self.closed:
- return
- i = self.next_len - self.buffer.tell()
- if i > len(s):
- self.buffer.write(s)
- return
- self.buffer.write(s[:i])
- s = s[i:]
- m = self.buffer.getvalue()
- self.buffer.reset()
- self.buffer.truncate()
- try:
- x = self.next_func(m)
- except:
- self.next_len, self.next_func = 1, self.read_dead
- raise
- if x is None:
- self.close()
- return
- if x == True: # ready to process
- self.multihandler.singlerawservers[m]._external_connection_made(
- self.connection, self.options, s)
- self.complete = True
- return
- self.next_len, self.next_func = x
-
- def connection_flushed(self, ss):
- pass
-
- def connection_lost(self, ss):
- self.closed = True
-
-class MultiHandler:
- def __init__(self, rawserver, doneflag):
- self.rawserver = rawserver
- self.masterdoneflag = doneflag
- self.singlerawservers = {}
- self.connections = {}
- self.taskqueues = {}
-
- def newRawServer(self, info_hash, doneflag, protocol=protocol_name):
- new = SingleRawServer(info_hash, self, doneflag, protocol)
- self.singlerawservers[info_hash] = new
- return new
-
- def shutdown_torrent(self, info_hash):
- self.singlerawservers[info_hash]._shutdown()
- del self.singlerawservers[info_hash]
-
- def listen_forever(self):
- self.rawserver.listen_forever(self)
- for srs in self.singlerawservers.values():
- srs.finished = True
- srs.running = False
- srs.doneflag.set()
-
- ### RawServer handler functions ###
- # be wary of name collisions
-
- def external_connection_made(self, ss):
- NewSocketHandler(self, ss)
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-import socket
-from errno import EWOULDBLOCK, ECONNREFUSED, EHOSTUNREACH
-try:
- from select import poll, error, POLLIN, POLLOUT, POLLERR, POLLHUP
- timemult = 1000
-except ImportError:
- from selectpoll import poll, error, POLLIN, POLLOUT, POLLERR, POLLHUP
- timemult = 1
-from time import sleep
-from clock import clock
-import sys
-from random import shuffle, randrange
-from natpunch import UPnP_open_port, UPnP_close_port
-# from BT1.StreamCheck import StreamCheck
-# import inspect
-try:
- True
-except:
- True = 1
- False = 0
-
-all = POLLIN | POLLOUT
-
-UPnP_ERROR = "unable to forward port via UPnP"
-
-class SingleSocket:
- def __init__(self, socket_handler, sock, handler, ip = None):
- self.socket_handler = socket_handler
- self.socket = sock
- self.handler = handler
- self.buffer = []
- self.last_hit = clock()
- self.fileno = sock.fileno()
- self.connected = False
- self.skipped = 0
-# self.check = StreamCheck()
- try:
- self.ip = self.socket.getpeername()[0]
- except:
- if ip is None:
- self.ip = 'unknown'
- else:
- self.ip = ip
-
- def get_ip(self, real=False):
- if real:
- try:
- self.ip = self.socket.getpeername()[0]
- except:
- pass
- return self.ip
-
- def close(self):
- '''
- for x in xrange(5,0,-1):
- try:
- f = inspect.currentframe(x).f_code
- print (f.co_filename,f.co_firstlineno,f.co_name)
- del f
- except:
- pass
- print ''
- '''
- assert self.socket
- self.connected = False
- sock = self.socket
- self.socket = None
- self.buffer = []
- del self.socket_handler.single_sockets[self.fileno]
- self.socket_handler.poll.unregister(sock)
- sock.close()
-
- def shutdown(self, val):
- self.socket.shutdown(val)
-
- def is_flushed(self):
- return not self.buffer
-
- def write(self, s):
-# self.check.write(s)
- assert self.socket is not None
- self.buffer.append(s)
- if len(self.buffer) == 1:
- self.try_write()
-
- def try_write(self):
- if self.connected:
- dead = False
- try:
- while self.buffer:
- buf = self.buffer[0]
- amount = self.socket.send(buf)
- if amount == 0:
- self.skipped += 1
- break
- self.skipped = 0
- if amount != len(buf):
- self.buffer[0] = buf[amount:]
- break
- del self.buffer[0]
- except socket.error, e:
- try:
- dead = e[0] != EWOULDBLOCK
- except:
- dead = True
- self.skipped += 1
- if self.skipped >= 3:
- dead = True
- if dead:
- self.socket_handler.dead_from_write.append(self)
- return
- if self.buffer:
- self.socket_handler.poll.register(self.socket, all)
- else:
- self.socket_handler.poll.register(self.socket, POLLIN)
-
- def set_handler(self, handler):
- self.handler = handler
-
-class SocketHandler:
- def __init__(self, timeout, ipv6_enable, readsize = 100000):
- self.timeout = timeout
- self.ipv6_enable = ipv6_enable
- self.readsize = readsize
- self.poll = poll()
- # {socket: SingleSocket}
- self.single_sockets = {}
- self.dead_from_write = []
- self.max_connects = 1000
- self.port_forwarded = None
- self.servers = {}
-
- def scan_for_timeouts(self):
- t = clock() - self.timeout
- tokill = []
- for s in self.single_sockets.values():
- if s.last_hit < t:
- tokill.append(s)
- for k in tokill:
- if k.socket is not None:
- self._close_socket(k)
-
- def bind(self, port, bind = '', reuse = False, ipv6_socket_style = 1, upnp = 0):
- port = int(port)
- addrinfos = []
- self.servers = {}
- self.interfaces = []
- # if bind != "" thread it as a comma seperated list and bind to all
- # addresses (can be ips or hostnames) else bind to default ipv6 and
- # ipv4 address
- if bind:
- if self.ipv6_enable:
- socktype = socket.AF_UNSPEC
- else:
- socktype = socket.AF_INET
- bind = bind.split(',')
- for addr in bind:
- if sys.version_info < (2,2):
- addrinfos.append((socket.AF_INET, None, None, None, (addr, port)))
- else:
- addrinfos.extend(socket.getaddrinfo(addr, port,
- socktype, socket.SOCK_STREAM))
- else:
- if self.ipv6_enable:
- addrinfos.append([socket.AF_INET6, None, None, None, ('', port)])
- if not addrinfos or ipv6_socket_style != 0:
- addrinfos.append([socket.AF_INET, None, None, None, ('', port)])
- for addrinfo in addrinfos:
- try:
- server = socket.socket(addrinfo[0], socket.SOCK_STREAM)
- if reuse:
- server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- server.setblocking(0)
- server.bind(addrinfo[4])
- self.servers[server.fileno()] = server
- if bind:
- self.interfaces.append(server.getsockname()[0])
- server.listen(64)
- self.poll.register(server, POLLIN)
- except socket.error, e:
- for server in self.servers.values():
- try:
- server.close()
- except:
- pass
- if self.ipv6_enable and ipv6_socket_style == 0 and self.servers:
- raise socket.error('blocked port (may require ipv6_binds_v4 to be set)')
- raise socket.error(str(e))
- if not self.servers:
- raise socket.error('unable to open server port')
- if upnp:
- if not UPnP_open_port(port):
- for server in self.servers.values():
- try:
- server.close()
- except:
- pass
- self.servers = None
- self.interfaces = None
- raise socket.error(UPnP_ERROR)
- self.port_forwarded = port
- self.port = port
-
- def find_and_bind(self, minport, maxport, bind = '', reuse = False,
- ipv6_socket_style = 1, upnp = 0, randomizer = False):
- e = 'maxport less than minport - no ports to check'
- if maxport-minport < 50 or not randomizer:
- portrange = range(minport, maxport+1)
- if randomizer:
- shuffle(portrange)
- portrange = portrange[:20] # check a maximum of 20 ports
- else:
- portrange = []
- while len(portrange) < 20:
- listen_port = randrange(minport, maxport+1)
- if not listen_port in portrange:
- portrange.append(listen_port)
- for listen_port in portrange:
- try:
- self.bind(listen_port, bind,
- ipv6_socket_style = ipv6_socket_style, upnp = upnp)
- return listen_port
- except socket.error, e:
- pass
- raise socket.error(str(e))
-
-
- def set_handler(self, handler):
- self.handler = handler
-
-
- def start_connection_raw(self, dns, socktype = socket.AF_INET, handler = None):
- if handler is None:
- handler = self.handler
- sock = socket.socket(socktype, socket.SOCK_STREAM)
- sock.setblocking(0)
- try:
- sock.connect_ex(dns)
- except socket.error:
- raise
- except Exception, e:
- raise socket.error(str(e))
- self.poll.register(sock, POLLIN)
- s = SingleSocket(self, sock, handler, dns[0])
- self.single_sockets[sock.fileno()] = s
- return s
-
-
- def start_connection(self, dns, handler = None, randomize = False):
- if handler is None:
- handler = self.handler
- if sys.version_info < (2,2):
- s = self.start_connection_raw(dns,socket.AF_INET,handler)
- else:
- if self.ipv6_enable:
- socktype = socket.AF_UNSPEC
- else:
- socktype = socket.AF_INET
- try:
- addrinfos = socket.getaddrinfo(dns[0], int(dns[1]),
- socktype, socket.SOCK_STREAM)
- except socket.error, e:
- raise
- except Exception, e:
- raise socket.error(str(e))
- if randomize:
- shuffle(addrinfos)
- for addrinfo in addrinfos:
- try:
- s = self.start_connection_raw(addrinfo[4],addrinfo[0],handler)
- break
- except:
- pass
- else:
- raise socket.error('unable to connect')
- return s
-
-
- def _sleep(self):
- sleep(1)
-
- def handle_events(self, events):
- for sock, event in events:
- s = self.servers.get(sock)
- if s:
- if event & (POLLHUP | POLLERR) != 0:
- self.poll.unregister(s)
- s.close()
- del self.servers[sock]
- print "lost server socket"
- elif len(self.single_sockets) < self.max_connects:
- try:
- newsock, addr = s.accept()
- newsock.setblocking(0)
- nss = SingleSocket(self, newsock, self.handler)
- self.single_sockets[newsock.fileno()] = nss
- self.poll.register(newsock, POLLIN)
- self.handler.external_connection_made(nss)
- except socket.error:
- self._sleep()
- else:
- s = self.single_sockets.get(sock)
- if not s:
- continue
- s.connected = True
- if (event & (POLLHUP | POLLERR)):
- self._close_socket(s)
- continue
- if (event & POLLIN):
- try:
- s.last_hit = clock()
- data = s.socket.recv(100000)
- if not data:
- self._close_socket(s)
- else:
- s.handler.data_came_in(s, data)
- except socket.error, e:
- code, msg = e
- if code != EWOULDBLOCK:
- self._close_socket(s)
- continue
- if (event & POLLOUT) and s.socket and not s.is_flushed():
- s.try_write()
- if s.is_flushed():
- s.handler.connection_flushed(s)
-
- def close_dead(self):
- while self.dead_from_write:
- old = self.dead_from_write
- self.dead_from_write = []
- for s in old:
- if s.socket:
- self._close_socket(s)
-
- def _close_socket(self, s):
- s.close()
- s.handler.connection_lost(s)
-
- def do_poll(self, t):
- r = self.poll.poll(t*timemult)
- if r is None:
- connects = len(self.single_sockets)
- to_close = int(connects*0.05)+1 # close 5% of sockets
- self.max_connects = connects-to_close
- closelist = self.single_sockets.values()
- shuffle(closelist)
- closelist = closelist[:to_close]
- for sock in closelist:
- self._close_socket(sock)
- return []
- return r
-
- def get_stats(self):
- return { 'interfaces': self.interfaces,
- 'port': self.port,
- 'upnp': self.port_forwarded is not None }
-
-
- def shutdown(self):
- for ss in self.single_sockets.values():
- try:
- ss.close()
- except:
- pass
- for server in self.servers.values():
- try:
- server.close()
- except:
- pass
- if self.port_forwarded is not None:
- UPnP_close_port(self.port_forwarded)
-
+++ /dev/null
-product_name = 'BitTornado'
-version_short = 'T-0.3.17'
-
-version = version_short+' ('+product_name+')'
-report_email = version_short+'@degreez.net'
-
-from types import StringType
-from sha import sha
-from time import time, clock
-try:
- from os import getpid
-except ImportError:
- def getpid():
- return 1
-
-mapbase64 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-'
-
-_idprefix = version_short[0]
-for subver in version_short[2:].split('.'):
- try:
- subver = int(subver)
- except:
- subver = 0
- _idprefix += mapbase64[subver]
-_idprefix += ('-' * (6-len(_idprefix)))
-_idrandom = [None]
-
-def resetPeerIDs():
- try:
- f = open('/dev/urandom','rb')
- x = f.read(20)
- f.close()
- except:
- x = ''
-
- l1 = 0
- t = clock()
- while t == clock():
- l1 += 1
- l2 = 0
- t = long(time()*100)
- while t == long(time()*100):
- l2 += 1
- l3 = 0
- if l2 < 1000:
- t = long(time()*10)
- while t == long(clock()*10):
- l3 += 1
- x += ( repr(time()) + '/' + str(time()) + '/'
- + str(l1) + '/' + str(l2) + '/' + str(l3) + '/'
- + str(getpid()) )
-
- s = ''
- for i in sha(x).digest()[-11:]:
- s += mapbase64[ord(i) & 0x3F]
- _idrandom[0] = s
-
-resetPeerIDs()
-
-def createPeerID(ins = '---'):
- assert type(ins) is StringType
- assert len(ins) == 3
- return _idprefix + ins + _idrandom[0]
+++ /dev/null
-# Written by Petru Paler, Uoti Urpala, Ross Cohen and John Hoffman
-# see LICENSE.txt for license information
-
-from types import IntType, LongType, StringType, ListType, TupleType, DictType
-try:
- from types import BooleanType
-except ImportError:
- BooleanType = None
-try:
- from types import UnicodeType
-except ImportError:
- UnicodeType = None
-from cStringIO import StringIO
-
-def decode_int(x, f):
- f += 1
- newf = x.index('e', f)
- try:
- n = int(x[f:newf])
- except:
- n = long(x[f:newf])
- if x[f] == '-':
- if x[f + 1] == '0':
- raise ValueError
- elif x[f] == '0' and newf != f+1:
- raise ValueError
- return (n, newf+1)
-
-def decode_string(x, f):
- colon = x.index(':', f)
- try:
- n = int(x[f:colon])
- except (OverflowError, ValueError):
- n = long(x[f:colon])
- if x[f] == '0' and colon != f+1:
- raise ValueError
- colon += 1
- return (x[colon:colon+n], colon+n)
-
-def decode_unicode(x, f):
- s, f = decode_string(x, f+1)
- return (s.decode('UTF-8'),f)
-
-def decode_list(x, f):
- r, f = [], f+1
- while x[f] != 'e':
- v, f = decode_func[x[f]](x, f)
- r.append(v)
- return (r, f + 1)
-
-def decode_dict(x, f):
- r, f = {}, f+1
- lastkey = None
- while x[f] != 'e':
- k, f = decode_string(x, f)
- if lastkey >= k:
- raise ValueError
- lastkey = k
- r[k], f = decode_func[x[f]](x, f)
- return (r, f + 1)
-
-decode_func = {}
-decode_func['l'] = decode_list
-decode_func['d'] = decode_dict
-decode_func['i'] = decode_int
-decode_func['0'] = decode_string
-decode_func['1'] = decode_string
-decode_func['2'] = decode_string
-decode_func['3'] = decode_string
-decode_func['4'] = decode_string
-decode_func['5'] = decode_string
-decode_func['6'] = decode_string
-decode_func['7'] = decode_string
-decode_func['8'] = decode_string
-decode_func['9'] = decode_string
-#decode_func['u'] = decode_unicode
-
-def bdecode(x, sloppy = 0):
- try:
- r, l = decode_func[x[0]](x, 0)
-# except (IndexError, KeyError):
- except (IndexError, KeyError, ValueError):
- raise ValueError, "bad bencoded data"
- if not sloppy and l != len(x):
- raise ValueError, "bad bencoded data"
- return r
-
-def test_bdecode():
- try:
- bdecode('0:0:')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('ie')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('i341foo382e')
- assert 0
- except ValueError:
- pass
- assert bdecode('i4e') == 4L
- assert bdecode('i0e') == 0L
- assert bdecode('i123456789e') == 123456789L
- assert bdecode('i-10e') == -10L
- try:
- bdecode('i-0e')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('i123')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('i6easd')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('35208734823ljdahflajhdf')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('2:abfdjslhfld')
- assert 0
- except ValueError:
- pass
- assert bdecode('0:') == ''
- assert bdecode('3:abc') == 'abc'
- assert bdecode('10:1234567890') == '1234567890'
- try:
- bdecode('02:xy')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('l')
- assert 0
- except ValueError:
- pass
- assert bdecode('le') == []
- try:
- bdecode('leanfdldjfh')
- assert 0
- except ValueError:
- pass
- assert bdecode('l0:0:0:e') == ['', '', '']
- try:
- bdecode('relwjhrlewjh')
- assert 0
- except ValueError:
- pass
- assert bdecode('li1ei2ei3ee') == [1, 2, 3]
- assert bdecode('l3:asd2:xye') == ['asd', 'xy']
- assert bdecode('ll5:Alice3:Bobeli2ei3eee') == [['Alice', 'Bob'], [2, 3]]
- try:
- bdecode('d')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('defoobar')
- assert 0
- except ValueError:
- pass
- assert bdecode('de') == {}
- assert bdecode('d3:agei25e4:eyes4:bluee') == {'age': 25, 'eyes': 'blue'}
- assert bdecode('d8:spam.mp3d6:author5:Alice6:lengthi100000eee') == {'spam.mp3': {'author': 'Alice', 'length': 100000}}
- try:
- bdecode('d3:fooe')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('di1e0:e')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('d1:b0:1:a0:e')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('d1:a0:1:a0:e')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('i03e')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('l01:ae')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('9999:x')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('l0:')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('d0:0:')
- assert 0
- except ValueError:
- pass
- try:
- bdecode('d0:')
- assert 0
- except ValueError:
- pass
-
-bencached_marker = []
-
-class Bencached:
- def __init__(self, s):
- self.marker = bencached_marker
- self.bencoded = s
-
-BencachedType = type(Bencached('')) # insufficient, but good as a filter
-
-def encode_bencached(x,r):
- assert x.marker == bencached_marker
- r.append(x.bencoded)
-
-def encode_int(x,r):
- r.extend(('i',str(x),'e'))
-
-def encode_bool(x,r):
- encode_int(int(x),r)
-
-def encode_string(x,r):
- r.extend((str(len(x)),':',x))
-
-def encode_unicode(x,r):
- #r.append('u')
- encode_string(x.encode('UTF-8'),r)
-
-def encode_list(x,r):
- r.append('l')
- for e in x:
- encode_func[type(e)](e, r)
- r.append('e')
-
-def encode_dict(x,r):
- r.append('d')
- ilist = x.items()
- ilist.sort()
- for k,v in ilist:
- r.extend((str(len(k)),':',k))
- encode_func[type(v)](v, r)
- r.append('e')
-
-encode_func = {}
-encode_func[BencachedType] = encode_bencached
-encode_func[IntType] = encode_int
-encode_func[LongType] = encode_int
-encode_func[StringType] = encode_string
-encode_func[ListType] = encode_list
-encode_func[TupleType] = encode_list
-encode_func[DictType] = encode_dict
-if BooleanType:
- encode_func[BooleanType] = encode_bool
-if UnicodeType:
- encode_func[UnicodeType] = encode_unicode
-
-def bencode(x):
- r = []
- try:
- encode_func[type(x)](x, r)
- except:
- print "*** error *** could not encode type %s (value: %s)" % (type(x), x)
- assert 0
- return ''.join(r)
-
-def test_bencode():
- assert bencode(4) == 'i4e'
- assert bencode(0) == 'i0e'
- assert bencode(-10) == 'i-10e'
- assert bencode(12345678901234567890L) == 'i12345678901234567890e'
- assert bencode('') == '0:'
- assert bencode('abc') == '3:abc'
- assert bencode('1234567890') == '10:1234567890'
- assert bencode([]) == 'le'
- assert bencode([1, 2, 3]) == 'li1ei2ei3ee'
- assert bencode([['Alice', 'Bob'], [2, 3]]) == 'll5:Alice3:Bobeli2ei3eee'
- assert bencode({}) == 'de'
- assert bencode({'age': 25, 'eyes': 'blue'}) == 'd3:agei25e4:eyes4:bluee'
- assert bencode({'spam.mp3': {'author': 'Alice', 'length': 100000}}) == 'd8:spam.mp3d6:author5:Alice6:lengthi100000eee'
- try:
- bencode({1: 'foo'})
- assert 0
- except AssertionError:
- pass
-
-
-try:
- import psyco
- psyco.bind(bdecode)
- psyco.bind(bencode)
-except ImportError:
- pass
+++ /dev/null
-# Written by Bram Cohen, Uoti Urpala, and John Hoffman
-# see LICENSE.txt for license information
-
-try:
- True
-except:
- True = 1
- False = 0
- bool = lambda x: not not x
-
-try:
- sum([1])
- negsum = lambda a: len(a)-sum(a)
-except:
- negsum = lambda a: reduce(lambda x,y: x+(not y), a, 0)
-
-def _int_to_booleans(x):
- r = []
- for i in range(8):
- r.append(bool(x & 0x80))
- x <<= 1
- return tuple(r)
-
-lookup_table = []
-reverse_lookup_table = {}
-for i in xrange(256):
- x = _int_to_booleans(i)
- lookup_table.append(x)
- reverse_lookup_table[x] = chr(i)
-
-
-class Bitfield:
- def __init__(self, length = None, bitstring = None, copyfrom = None):
- if copyfrom is not None:
- self.length = copyfrom.length
- self.array = copyfrom.array[:]
- self.numfalse = copyfrom.numfalse
- return
- if length is None:
- raise ValueError, "length must be provided unless copying from another array"
- self.length = length
- if bitstring is not None:
- extra = len(bitstring) * 8 - length
- if extra < 0 or extra >= 8:
- raise ValueError
- t = lookup_table
- r = []
- for c in bitstring:
- r.extend(t[ord(c)])
- if extra > 0:
- if r[-extra:] != [0] * extra:
- raise ValueError
- del r[-extra:]
- self.array = r
- self.numfalse = negsum(r)
- else:
- self.array = [False] * length
- self.numfalse = length
-
- def __setitem__(self, index, val):
- val = bool(val)
- self.numfalse += self.array[index]-val
- self.array[index] = val
-
- def __getitem__(self, index):
- return self.array[index]
-
- def __len__(self):
- return self.length
-
- def tostring(self):
- booleans = self.array
- t = reverse_lookup_table
- s = len(booleans) % 8
- r = [ t[tuple(booleans[x:x+8])] for x in xrange(0, len(booleans)-s, 8) ]
- if s:
- r += t[tuple(booleans[-s:] + ([0] * (8-s)))]
- return ''.join(r)
-
- def complete(self):
- return not self.numfalse
-
-
-def test_bitfield():
- try:
- x = Bitfield(7, 'ab')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(7, 'ab')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(9, 'abc')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(0, 'a')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(1, '')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(7, '')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(8, '')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(9, 'a')
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(7, chr(1))
- assert False
- except ValueError:
- pass
- try:
- x = Bitfield(9, chr(0) + chr(0x40))
- assert False
- except ValueError:
- pass
- assert Bitfield(0, '').tostring() == ''
- assert Bitfield(1, chr(0x80)).tostring() == chr(0x80)
- assert Bitfield(7, chr(0x02)).tostring() == chr(0x02)
- assert Bitfield(8, chr(0xFF)).tostring() == chr(0xFF)
- assert Bitfield(9, chr(0) + chr(0x80)).tostring() == chr(0) + chr(0x80)
- x = Bitfield(1)
- assert x.numfalse == 1
- x[0] = 1
- assert x.numfalse == 0
- x[0] = 1
- assert x.numfalse == 0
- assert x.tostring() == chr(0x80)
- x = Bitfield(7)
- assert len(x) == 7
- x[6] = 1
- assert x.numfalse == 6
- assert x.tostring() == chr(0x02)
- x = Bitfield(8)
- x[7] = 1
- assert x.tostring() == chr(1)
- x = Bitfield(9)
- x[8] = 1
- assert x.numfalse == 8
- assert x.tostring() == chr(0) + chr(0x80)
- x = Bitfield(8, chr(0xC4))
- assert len(x) == 8
- assert x.numfalse == 5
- assert x.tostring() == chr(0xC4)
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from time import *
-import sys
-
-_MAXFORWARD = 100
-_FUDGE = 1
-
-class RelativeTime:
- def __init__(self):
- self.time = time()
- self.offset = 0
-
- def get_time(self):
- t = time() + self.offset
- if t < self.time or t > self.time + _MAXFORWARD:
- self.time += _FUDGE
- self.offset += self.time - t
- return self.time
- self.time = t
- return t
-
-if sys.platform != 'win32':
- _RTIME = RelativeTime()
- def clock():
- return _RTIME.get_time()
\ No newline at end of file
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from zurllib import urlopen
-from urlparse import urlparse
-from BT1.btformats import check_message
-from BT1.Choker import Choker
-from BT1.Storage import Storage
-from BT1.StorageWrapper import StorageWrapper
-from BT1.FileSelector import FileSelector
-from BT1.Uploader import Upload
-from BT1.Downloader import Downloader
-from BT1.HTTPDownloader import HTTPDownloader
-from BT1.Connecter import Connecter
-from RateLimiter import RateLimiter
-from BT1.Encrypter import Encoder
-from RawServer import RawServer, autodetect_ipv6, autodetect_socket_style
-from BT1.Rerequester import Rerequester
-from BT1.DownloaderFeedback import DownloaderFeedback
-from RateMeasure import RateMeasure
-from CurrentRateMeasure import Measure
-from BT1.PiecePicker import PiecePicker
-from BT1.Statistics import Statistics
-from ConfigDir import ConfigDir
-from bencode import bencode, bdecode
-from natpunch import UPnP_test
-from sha import sha
-from os import path, makedirs, listdir
-from parseargs import parseargs, formatDefinitions, defaultargs
-from socket import error as socketerror
-from random import seed
-from threading import Thread, Event
-from clock import clock
-from __init__ import createPeerID
-
-try:
- True
-except:
- True = 1
- False = 0
-
-defaults = [
- ('max_uploads', 7,
- "the maximum number of uploads to allow at once."),
- ('keepalive_interval', 120.0,
- 'number of seconds to pause between sending keepalives'),
- ('download_slice_size', 2 ** 14,
- "How many bytes to query for per request."),
- ('upload_unit_size', 1460,
- "when limiting upload rate, how many bytes to send at a time"),
- ('request_backlog', 10,
- "maximum number of requests to keep in a single pipe at once."),
- ('max_message_length', 2 ** 23,
- "maximum length prefix encoding you'll accept over the wire - larger values get the connection dropped."),
- ('ip', '',
- "ip to report you have to the tracker."),
- ('minport', 10000, 'minimum port to listen on, counts up if unavailable'),
- ('maxport', 60000, 'maximum port to listen on'),
- ('random_port', 1, 'whether to choose randomly inside the port range ' +
- 'instead of counting up linearly'),
- ('responsefile', '',
- 'file the server response was stored in, alternative to url'),
- ('url', '',
- 'url to get file from, alternative to responsefile'),
- ('selector_enabled', 1,
- 'whether to enable the file selector and fast resume function'),
- ('expire_cache_data', 10,
- 'the number of days after which you wish to expire old cache data ' +
- '(0 = disabled)'),
- ('priority', '',
- 'a list of file priorities separated by commas, must be one per file, ' +
- '0 = highest, 1 = normal, 2 = lowest, -1 = download disabled'),
- ('saveas', '',
- 'local file name to save the file as, null indicates query user'),
- ('timeout', 300.0,
- 'time to wait between closing sockets which nothing has been received on'),
- ('timeout_check_interval', 60.0,
- 'time to wait between checking if any connections have timed out'),
- ('max_slice_length', 2 ** 17,
- "maximum length slice to send to peers, larger requests are ignored"),
- ('max_rate_period', 20.0,
- "maximum amount of time to guess the current rate estimate represents"),
- ('bind', '',
- 'comma-separated list of ips/hostnames to bind to locally'),
-# ('ipv6_enabled', autodetect_ipv6(),
- ('ipv6_enabled', 0,
- 'allow the client to connect to peers via IPv6'),
- ('ipv6_binds_v4', autodetect_socket_style(),
- "set if an IPv6 server socket won't also field IPv4 connections"),
- ('upnp_nat_access', 1,
- 'attempt to autoconfigure a UPnP router to forward a server port ' +
- '(0 = disabled, 1 = mode 1 [fast], 2 = mode 2 [slow])'),
- ('upload_rate_fudge', 5.0,
- 'time equivalent of writing to kernel-level TCP buffer, for rate adjustment'),
- ('tcp_ack_fudge', 0.03,
- 'how much TCP ACK download overhead to add to upload rate calculations ' +
- '(0 = disabled)'),
- ('display_interval', .5,
- 'time between updates of displayed information'),
- ('rerequest_interval', 5 * 60,
- 'time to wait between requesting more peers'),
- ('min_peers', 20,
- 'minimum number of peers to not do rerequesting'),
- ('http_timeout', 60,
- 'number of seconds to wait before assuming that an http connection has timed out'),
- ('max_initiate', 40,
- 'number of peers at which to stop initiating new connections'),
- ('check_hashes', 1,
- 'whether to check hashes on disk'),
- ('max_upload_rate', 0,
- 'maximum kB/s to upload at (0 = no limit, -1 = automatic)'),
- ('max_download_rate', 0,
- 'maximum kB/s to download at (0 = no limit)'),
- ('alloc_type', 'normal',
- 'allocation type (may be normal, background, pre-allocate or sparse)'),
- ('alloc_rate', 2.0,
- 'rate (in MiB/s) to allocate space at using background allocation'),
- ('buffer_reads', 1,
- 'whether to buffer disk reads'),
- ('write_buffer_size', 4,
- 'the maximum amount of space to use for buffering disk writes ' +
- '(in megabytes, 0 = disabled)'),
- ('breakup_seed_bitfield', 1,
- 'sends an incomplete bitfield and then fills with have messages, '
- 'in order to get around stupid ISP manipulation'),
- ('snub_time', 30.0,
- "seconds to wait for data to come in over a connection before assuming it's semi-permanently choked"),
- ('spew', 0,
- "whether to display diagnostic info to stdout"),
- ('rarest_first_cutoff', 2,
- "number of downloads at which to switch from random to rarest first"),
- ('rarest_first_priority_cutoff', 5,
- 'the number of peers which need to have a piece before other partials take priority over rarest first'),
- ('min_uploads', 4,
- "the number of uploads to fill out to with extra optimistic unchokes"),
- ('max_files_open', 50,
- 'the maximum number of files to keep open at a time, 0 means no limit'),
- ('round_robin_period', 30,
- "the number of seconds between the client's switching upload targets"),
- ('super_seeder', 0,
- "whether to use special upload-efficiency-maximizing routines (only for dedicated seeds)"),
- ('security', 1,
- "whether to enable extra security features intended to prevent abuse"),
- ('max_connections', 0,
- "the absolute maximum number of peers to connect with (0 = no limit)"),
- ('auto_kick', 1,
- "whether to allow the client to automatically kick/ban peers that send bad data"),
- ('double_check', 1,
- "whether to double-check data being written to the disk for errors (may increase CPU load)"),
- ('triple_check', 0,
- "whether to thoroughly check data being written to the disk (may slow disk access)"),
- ('lock_files', 1,
- "whether to lock files the client is working with"),
- ('lock_while_reading', 0,
- "whether to lock access to files being read"),
- ('auto_flush', 0,
- "minutes between automatic flushes to disk (0 = disabled)"),
- ('dedicated_seed_id', '',
- "code to send to tracker identifying as a dedicated seed"),
- ]
-
-argslistheader = 'Arguments are:\n\n'
-
-
-def _failfunc(x):
- print x
-
-# old-style downloader
-def download(params, filefunc, statusfunc, finfunc, errorfunc, doneflag, cols,
- pathFunc = None, presets = {}, exchandler = None,
- failed = _failfunc, paramfunc = None):
-
- try:
- config = parse_params(params, presets)
- except ValueError, e:
- failed('error: ' + str(e) + '\nrun with no args for parameter explanations')
- return
- if not config:
- errorfunc(get_usage())
- return
-
- myid = createPeerID()
- seed(myid)
-
- rawserver = RawServer(doneflag, config['timeout_check_interval'],
- config['timeout'], ipv6_enable = config['ipv6_enabled'],
- failfunc = failed, errorfunc = exchandler)
-
- upnp_type = UPnP_test(config['upnp_nat_access'])
- try:
- listen_port = rawserver.find_and_bind(config['minport'], config['maxport'],
- config['bind'], ipv6_socket_style = config['ipv6_binds_v4'],
- upnp = upnp_type, randomizer = config['random_port'])
- except socketerror, e:
- failed("Couldn't listen - " + str(e))
- return
-
- response = get_response(config['responsefile'], config['url'], failed)
- if not response:
- return
-
- infohash = sha(bencode(response['info'])).digest()
-
- d = BT1Download(statusfunc, finfunc, errorfunc, exchandler, doneflag,
- config, response, infohash, myid, rawserver, listen_port)
-
- if not d.saveAs(filefunc):
- return
-
- if pathFunc:
- pathFunc(d.getFilename())
-
- hashcheck = d.initFiles(old_style = True)
- if not hashcheck:
- return
- if not hashcheck():
- return
- if not d.startEngine():
- return
- d.startRerequester()
- d.autoStats()
-
- statusfunc(activity = 'connecting to peers')
-
- if paramfunc:
- paramfunc({ 'max_upload_rate' : d.setUploadRate, # change_max_upload_rate(<int KiB/sec>)
- 'max_uploads': d.setConns, # change_max_uploads(<int max uploads>)
- 'listen_port' : listen_port, # int
- 'peer_id' : myid, # string
- 'info_hash' : infohash, # string
- 'start_connection' : d._startConnection, # start_connection((<string ip>, <int port>), <peer id>)
- })
-
- rawserver.listen_forever(d.getPortHandler())
-
- d.shutdown()
-
-
-def parse_params(params, presets = {}):
- if len(params) == 0:
- return None
- config, args = parseargs(params, defaults, 0, 1, presets = presets)
- if args:
- if config['responsefile'] or config['url']:
- raise ValueError,'must have responsefile or url as arg or parameter, not both'
- if path.isfile(args[0]):
- config['responsefile'] = args[0]
- else:
- try:
- urlparse(args[0])
- except:
- raise ValueError, 'bad filename or url'
- config['url'] = args[0]
- elif (config['responsefile'] == '') == (config['url'] == ''):
- raise ValueError, 'need responsefile or url, must have one, cannot have both'
- return config
-
-
-def get_usage(defaults = defaults, cols = 100, presets = {}):
- return (argslistheader + formatDefinitions(defaults, cols, presets))
-
-
-def get_response(file, url, errorfunc):
- try:
- if file:
- h = open(file, 'rb')
- try:
- line = h.read(10) # quick test to see if responsefile contains a dict
- front,garbage = line.split(':',1)
- assert front[0] == 'd'
- int(front[1:])
- except:
- errorfunc(file+' is not a valid responsefile')
- return None
- try:
- h.seek(0)
- except:
- try:
- h.close()
- except:
- pass
- h = open(file, 'rb')
- else:
- try:
- h = urlopen(url)
- except:
- errorfunc(url+' bad url')
- return None
- response = h.read()
-
- except IOError, e:
- errorfunc('problem getting response info - ' + str(e))
- return None
- try:
- h.close()
- except:
- pass
- try:
- try:
- response = bdecode(response)
- except:
- errorfunc("warning: bad data in responsefile")
- response = bdecode(response, sloppy=1)
- check_message(response)
- except ValueError, e:
- errorfunc("got bad file info - " + str(e))
- return None
-
- return response
-
-
-class BT1Download:
- def __init__(self, statusfunc, finfunc, errorfunc, excfunc, doneflag,
- config, response, infohash, id, rawserver, port,
- appdataobj = None):
- self.statusfunc = statusfunc
- self.finfunc = finfunc
- self.errorfunc = errorfunc
- self.excfunc = excfunc
- self.doneflag = doneflag
- self.config = config
- self.response = response
- self.infohash = infohash
- self.myid = id
- self.rawserver = rawserver
- self.port = port
-
- self.info = self.response['info']
- self.pieces = [self.info['pieces'][x:x+20]
- for x in xrange(0, len(self.info['pieces']), 20)]
- self.len_pieces = len(self.pieces)
- self.argslistheader = argslistheader
- self.unpauseflag = Event()
- self.unpauseflag.set()
- self.downloader = None
- self.storagewrapper = None
- self.fileselector = None
- self.super_seeding_active = False
- self.filedatflag = Event()
- self.spewflag = Event()
- self.superseedflag = Event()
- self.whenpaused = None
- self.finflag = Event()
- self.rerequest = None
- self.tcp_ack_fudge = config['tcp_ack_fudge']
-
- self.selector_enabled = config['selector_enabled']
- if appdataobj:
- self.appdataobj = appdataobj
- elif self.selector_enabled:
- self.appdataobj = ConfigDir()
- self.appdataobj.deleteOldCacheData( config['expire_cache_data'],
- [self.infohash] )
-
- self.excflag = self.rawserver.get_exception_flag()
- self.failed = False
- self.checking = False
- self.started = False
-
- self.picker = PiecePicker(self.len_pieces, config['rarest_first_cutoff'],
- config['rarest_first_priority_cutoff'])
- self.choker = Choker(config, rawserver.add_task,
- self.picker, self.finflag.isSet)
-
-
- def checkSaveLocation(self, loc):
- if self.info.has_key('length'):
- return path.exists(loc)
- for x in self.info['files']:
- if path.exists(path.join(loc, x['path'][0])):
- return True
- return False
-
-
- def saveAs(self, filefunc, pathfunc = None):
- try:
- def make(f, forcedir = False):
- if not forcedir:
- f = path.split(f)[0]
- if f != '' and not path.exists(f):
- makedirs(f)
-
- if self.info.has_key('length'):
- file_length = self.info['length']
- file = filefunc(self.info['name'], file_length,
- self.config['saveas'], False)
- if file is None:
- return None
- make(file)
- files = [(file, file_length)]
- else:
- file_length = 0L
- for x in self.info['files']:
- file_length += x['length']
- file = filefunc(self.info['name'], file_length,
- self.config['saveas'], True)
- if file is None:
- return None
-
- # if this path exists, and no files from the info dict exist, we assume it's a new download and
- # the user wants to create a new directory with the default name
- existing = 0
- if path.exists(file):
- if not path.isdir(file):
- self.errorfunc(file + 'is not a dir')
- return None
- if len(listdir(file)) > 0: # if it's not empty
- for x in self.info['files']:
- if path.exists(path.join(file, x['path'][0])):
- existing = 1
- if not existing:
- file = path.join(file, self.info['name'])
- if path.exists(file) and not path.isdir(file):
- if file[-8:] == '.torrent':
- file = file[:-8]
- if path.exists(file) and not path.isdir(file):
- self.errorfunc("Can't create dir - " + self.info['name'])
- return None
- make(file, True)
-
- # alert the UI to any possible change in path
- if pathfunc != None:
- pathfunc(file)
-
- files = []
- for x in self.info['files']:
- n = file
- for i in x['path']:
- n = path.join(n, i)
- files.append((n, x['length']))
- make(n)
- except OSError, e:
- self.errorfunc("Couldn't allocate dir - " + str(e))
- return None
-
- self.filename = file
- self.files = files
- self.datalength = file_length
-
- return file
-
-
- def getFilename(self):
- return self.filename
-
-
- def _finished(self):
- self.finflag.set()
- try:
- self.storage.set_readonly()
- except (IOError, OSError), e:
- self.errorfunc('trouble setting readonly at end - ' + str(e))
- if self.superseedflag.isSet():
- self._set_super_seed()
- self.choker.set_round_robin_period(
- max( self.config['round_robin_period'],
- self.config['round_robin_period'] *
- self.info['piece length'] / 200000 ) )
- self.rerequest_complete()
- self.finfunc()
-
- def _data_flunked(self, amount, index):
- self.ratemeasure_datarejected(amount)
- if not self.doneflag.isSet():
- self.errorfunc('piece %d failed hash check, re-downloading it' % index)
-
- def _failed(self, reason):
- self.failed = True
- self.doneflag.set()
- if reason is not None:
- self.errorfunc(reason)
-
-
- def initFiles(self, old_style = False, statusfunc = None):
- if self.doneflag.isSet():
- return None
- if not statusfunc:
- statusfunc = self.statusfunc
-
- disabled_files = None
- if self.selector_enabled:
- self.priority = self.config['priority']
- if self.priority:
- try:
- self.priority = self.priority.split(',')
- assert len(self.priority) == len(self.files)
- self.priority = [int(p) for p in self.priority]
- for p in self.priority:
- assert p >= -1
- assert p <= 2
- except:
- self.errorfunc('bad priority list given, ignored')
- self.priority = None
-
- data = self.appdataobj.getTorrentData(self.infohash)
- try:
- d = data['resume data']['priority']
- assert len(d) == len(self.files)
- disabled_files = [x == -1 for x in d]
- except:
- try:
- disabled_files = [x == -1 for x in self.priority]
- except:
- pass
-
- try:
- try:
- self.storage = Storage(self.files, self.info['piece length'],
- self.doneflag, self.config, disabled_files)
- except IOError, e:
- self.errorfunc('trouble accessing files - ' + str(e))
- return None
- if self.doneflag.isSet():
- return None
-
- self.storagewrapper = StorageWrapper(self.storage, self.config['download_slice_size'],
- self.pieces, self.info['piece length'], self._finished, self._failed,
- statusfunc, self.doneflag, self.config['check_hashes'],
- self._data_flunked, self.rawserver.add_task,
- self.config, self.unpauseflag)
-
- except ValueError, e:
- self._failed('bad data - ' + str(e))
- except IOError, e:
- self._failed('IOError - ' + str(e))
- if self.doneflag.isSet():
- return None
-
- if self.selector_enabled:
- self.fileselector = FileSelector(self.files, self.info['piece length'],
- self.appdataobj.getPieceDir(self.infohash),
- self.storage, self.storagewrapper,
- self.rawserver.add_task,
- self._failed)
- if data:
- data = data.get('resume data')
- if data:
- self.fileselector.unpickle(data)
-
- self.checking = True
- if old_style:
- return self.storagewrapper.old_style_init()
- return self.storagewrapper.initialize
-
-
- def getCachedTorrentData(self):
- return self.appdataobj.getTorrentData(self.infohash)
-
-
- def _make_upload(self, connection, ratelimiter, totalup):
- return Upload(connection, ratelimiter, totalup,
- self.choker, self.storagewrapper, self.picker,
- self.config)
-
- def _kick_peer(self, connection):
- def k(connection = connection):
- connection.close()
- self.rawserver.add_task(k,0)
-
- def _ban_peer(self, ip):
- self.encoder_ban(ip)
-
- def _received_raw_data(self, x):
- if self.tcp_ack_fudge:
- x = int(x*self.tcp_ack_fudge)
- self.ratelimiter.adjust_sent(x)
-# self.upmeasure.update_rate(x)
-
- def _received_data(self, x):
- self.downmeasure.update_rate(x)
- self.ratemeasure.data_came_in(x)
-
- def _received_http_data(self, x):
- self.downmeasure.update_rate(x)
- self.ratemeasure.data_came_in(x)
- self.downloader.external_data_received(x)
-
- def _cancelfunc(self, pieces):
- self.downloader.cancel_piece_download(pieces)
- self.httpdownloader.cancel_piece_download(pieces)
- def _reqmorefunc(self, pieces):
- self.downloader.requeue_piece_download(pieces)
-
- def startEngine(self, ratelimiter = None, statusfunc = None):
- if self.doneflag.isSet():
- return False
- if not statusfunc:
- statusfunc = self.statusfunc
-
- self.checking = False
-
- for i in xrange(self.len_pieces):
- if self.storagewrapper.do_I_have(i):
- self.picker.complete(i)
- self.upmeasure = Measure(self.config['max_rate_period'],
- self.config['upload_rate_fudge'])
- self.downmeasure = Measure(self.config['max_rate_period'])
-
- if ratelimiter:
- self.ratelimiter = ratelimiter
- else:
- self.ratelimiter = RateLimiter(self.rawserver.add_task,
- self.config['upload_unit_size'],
- self.setConns)
- self.ratelimiter.set_upload_rate(self.config['max_upload_rate'])
-
- self.ratemeasure = RateMeasure()
- self.ratemeasure_datarejected = self.ratemeasure.data_rejected
-
- self.downloader = Downloader(self.storagewrapper, self.picker,
- self.config['request_backlog'], self.config['max_rate_period'],
- self.len_pieces, self.config['download_slice_size'],
- self._received_data, self.config['snub_time'], self.config['auto_kick'],
- self._kick_peer, self._ban_peer)
- self.downloader.set_download_rate(self.config['max_download_rate'])
- self.connecter = Connecter(self._make_upload, self.downloader, self.choker,
- self.len_pieces, self.upmeasure, self.config,
- self.ratelimiter, self.rawserver.add_task)
- self.encoder = Encoder(self.connecter, self.rawserver,
- self.myid, self.config['max_message_length'], self.rawserver.add_task,
- self.config['keepalive_interval'], self.infohash,
- self._received_raw_data, self.config)
- self.encoder_ban = self.encoder.ban
-
- self.httpdownloader = HTTPDownloader(self.storagewrapper, self.picker,
- self.rawserver, self.finflag, self.errorfunc, self.downloader,
- self.config['max_rate_period'], self.infohash, self._received_http_data,
- self.connecter.got_piece)
- if self.response.has_key('httpseeds') and not self.finflag.isSet():
- for u in self.response['httpseeds']:
- self.httpdownloader.make_download(u)
-
- if self.selector_enabled:
- self.fileselector.tie_in(self.picker, self._cancelfunc,
- self._reqmorefunc, self.rerequest_ondownloadmore)
- if self.priority:
- self.fileselector.set_priorities_now(self.priority)
- self.appdataobj.deleteTorrentData(self.infohash)
- # erase old data once you've started modifying it
-
- if self.config['super_seeder']:
- self.set_super_seed()
-
- self.started = True
- return True
-
-
- def rerequest_complete(self):
- if self.rerequest:
- self.rerequest.announce(1)
-
- def rerequest_stopped(self):
- if self.rerequest:
- self.rerequest.announce(2)
-
- def rerequest_lastfailed(self):
- if self.rerequest:
- return self.rerequest.last_failed
- return False
-
- def rerequest_ondownloadmore(self):
- if self.rerequest:
- self.rerequest.hit()
-
- def startRerequester(self, seededfunc = None, force_rapid_update = False):
- if self.response.has_key('announce-list'):
- trackerlist = self.response['announce-list']
- else:
- trackerlist = [[self.response['announce']]]
-
- self.rerequest = Rerequester(trackerlist, self.config['rerequest_interval'],
- self.rawserver.add_task, self.connecter.how_many_connections,
- self.config['min_peers'], self.encoder.start_connections,
- self.rawserver.add_task, self.storagewrapper.get_amount_left,
- self.upmeasure.get_total, self.downmeasure.get_total, self.port, self.config['ip'],
- self.myid, self.infohash, self.config['http_timeout'],
- self.errorfunc, self.excfunc, self.config['max_initiate'],
- self.doneflag, self.upmeasure.get_rate, self.downmeasure.get_rate,
- self.unpauseflag, self.config['dedicated_seed_id'],
- seededfunc, force_rapid_update )
-
- self.rerequest.start()
-
-
- def _init_stats(self):
- self.statistics = Statistics(self.upmeasure, self.downmeasure,
- self.connecter, self.httpdownloader, self.ratelimiter,
- self.rerequest_lastfailed, self.filedatflag)
- if self.info.has_key('files'):
- self.statistics.set_dirstats(self.files, self.info['piece length'])
- if self.config['spew']:
- self.spewflag.set()
-
- def autoStats(self, displayfunc = None):
- if not displayfunc:
- displayfunc = self.statusfunc
-
- self._init_stats()
- DownloaderFeedback(self.choker, self.httpdownloader, self.rawserver.add_task,
- self.upmeasure.get_rate, self.downmeasure.get_rate,
- self.ratemeasure, self.storagewrapper.get_stats,
- self.datalength, self.finflag, self.spewflag, self.statistics,
- displayfunc, self.config['display_interval'])
-
- def startStats(self):
- self._init_stats()
- d = DownloaderFeedback(self.choker, self.httpdownloader, self.rawserver.add_task,
- self.upmeasure.get_rate, self.downmeasure.get_rate,
- self.ratemeasure, self.storagewrapper.get_stats,
- self.datalength, self.finflag, self.spewflag, self.statistics)
- return d.gather
-
-
- def getPortHandler(self):
- return self.encoder
-
-
- def shutdown(self, torrentdata = {}):
- if self.checking or self.started:
- self.storagewrapper.sync()
- self.storage.close()
- self.rerequest_stopped()
- if self.fileselector and self.started:
- if not self.failed:
- self.fileselector.finish()
- torrentdata['resume data'] = self.fileselector.pickle()
- try:
- self.appdataobj.writeTorrentData(self.infohash,torrentdata)
- except:
- self.appdataobj.deleteTorrentData(self.infohash) # clear it
- return not self.failed and not self.excflag.isSet()
- # if returns false, you may wish to auto-restart the torrent
-
-
- def setUploadRate(self, rate):
- try:
- def s(self = self, rate = rate):
- self.config['max_upload_rate'] = rate
- self.ratelimiter.set_upload_rate(rate)
- self.rawserver.add_task(s)
- except AttributeError:
- pass
-
- def setConns(self, conns, conns2 = None):
- if not conns2:
- conns2 = conns
- try:
- def s(self = self, conns = conns, conns2 = conns2):
- self.config['min_uploads'] = conns
- self.config['max_uploads'] = conns2
- if (conns > 30):
- self.config['max_initiate'] = conns + 10
- self.rawserver.add_task(s)
- except AttributeError:
- pass
-
- def setDownloadRate(self, rate):
- try:
- def s(self = self, rate = rate):
- self.config['max_download_rate'] = rate
- self.downloader.set_download_rate(rate)
- self.rawserver.add_task(s)
- except AttributeError:
- pass
-
- def startConnection(self, ip, port, id):
- self.encoder._start_connection((ip, port), id)
-
- def _startConnection(self, ipandport, id):
- self.encoder._start_connection(ipandport, id)
-
- def setInitiate(self, initiate):
- try:
- def s(self = self, initiate = initiate):
- self.config['max_initiate'] = initiate
- self.rawserver.add_task(s)
- except AttributeError:
- pass
-
- def getConfig(self):
- return self.config
-
- def getDefaults(self):
- return defaultargs(defaults)
-
- def getUsageText(self):
- return self.argslistheader
-
- def reannounce(self, special = None):
- try:
- def r(self = self, special = special):
- if special is None:
- self.rerequest.announce()
- else:
- self.rerequest.announce(specialurl = special)
- self.rawserver.add_task(r)
- except AttributeError:
- pass
-
- def getResponse(self):
- try:
- return self.response
- except:
- return None
-
-# def Pause(self):
-# try:
-# if self.storagewrapper:
-# self.rawserver.add_task(self._pausemaker, 0)
-# except:
-# return False
-# self.unpauseflag.clear()
-# return True
-#
-# def _pausemaker(self):
-# self.whenpaused = clock()
-# self.unpauseflag.wait() # sticks a monkey wrench in the main thread
-#
-# def Unpause(self):
-# self.unpauseflag.set()
-# if self.whenpaused and clock()-self.whenpaused > 60:
-# def r(self = self):
-# self.rerequest.announce(3) # rerequest automatically if paused for >60 seconds
-# self.rawserver.add_task(r)
-
- def Pause(self):
- if not self.storagewrapper:
- return False
- self.unpauseflag.clear()
- self.rawserver.add_task(self.onPause)
- return True
-
- def onPause(self):
- self.whenpaused = clock()
- if not self.downloader:
- return
- self.downloader.pause(True)
- self.encoder.pause(True)
- self.choker.pause(True)
-
- def Unpause(self):
- self.unpauseflag.set()
- self.rawserver.add_task(self.onUnpause)
-
- def onUnpause(self):
- if not self.downloader:
- return
- self.downloader.pause(False)
- self.encoder.pause(False)
- self.choker.pause(False)
- if self.rerequest and self.whenpaused and clock()-self.whenpaused > 60:
- self.rerequest.announce(3) # rerequest automatically if paused for >60 seconds
-
- def set_super_seed(self):
- try:
- self.superseedflag.set()
- def s(self = self):
- if self.finflag.isSet():
- self._set_super_seed()
- self.rawserver.add_task(s)
- except AttributeError:
- pass
-
- def _set_super_seed(self):
- if not self.super_seeding_active:
- self.super_seeding_active = True
- self.errorfunc(' ** SUPER-SEED OPERATION ACTIVE **\n' +
- ' please set Max uploads so each peer gets 6-8 kB/s')
- def s(self = self):
- self.downloader.set_super_seed()
- self.choker.set_super_seed()
- self.rawserver.add_task(s)
- if self.finflag.isSet(): # mode started when already finished
- def r(self = self):
- self.rerequest.announce(3) # so after kicking everyone off, reannounce
- self.rawserver.add_task(r)
-
- def am_I_finished(self):
- return self.finflag.isSet()
-
- def get_transfer_stats(self):
- return self.upmeasure.get_total(), self.downmeasure.get_total()
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-'''
-reads/writes a Windows-style INI file
-format:
-
- aa = "bb"
- cc = 11
-
- [eee]
- ff = "gg"
-
-decodes to:
-d = { '': {'aa':'bb','cc':'11'}, 'eee': {'ff':'gg'} }
-
-the encoder can also take this as input:
-
-d = { 'aa': 'bb, 'cc': 11, 'eee': {'ff':'gg'} }
-
-though it will only decode in the above format. Keywords must be strings.
-Values that are strings are written surrounded by quotes, and the decoding
-routine automatically strips any.
-Booleans are written as integers. Anything else aside from string/int/float
-may have unpredictable results.
-'''
-
-from cStringIO import StringIO
-from traceback import print_exc
-from types import DictType, StringType
-try:
- from types import BooleanType
-except ImportError:
- BooleanType = None
-
-try:
- True
-except:
- True = 1
- False = 0
-
-DEBUG = False
-
-def ini_write(f, d, comment=''):
- try:
- a = {'':{}}
- for k,v in d.items():
- assert type(k) == StringType
- k = k.lower()
- if type(v) == DictType:
- if DEBUG:
- print 'new section:' +k
- if k:
- assert not a.has_key(k)
- a[k] = {}
- aa = a[k]
- for kk,vv in v:
- assert type(kk) == StringType
- kk = kk.lower()
- assert not aa.has_key(kk)
- if type(vv) == BooleanType:
- vv = int(vv)
- if type(vv) == StringType:
- vv = '"'+vv+'"'
- aa[kk] = str(vv)
- if DEBUG:
- print 'a['+k+']['+kk+'] = '+str(vv)
- else:
- aa = a['']
- assert not aa.has_key(k)
- if type(v) == BooleanType:
- v = int(v)
- if type(v) == StringType:
- v = '"'+v+'"'
- aa[k] = str(v)
- if DEBUG:
- print 'a[\'\']['+k+'] = '+str(v)
- r = open(f,'w')
- if comment:
- for c in comment.split('\n'):
- r.write('# '+c+'\n')
- r.write('\n')
- l = a.keys()
- l.sort()
- for k in l:
- if k:
- r.write('\n['+k+']\n')
- aa = a[k]
- ll = aa.keys()
- ll.sort()
- for kk in ll:
- r.write(kk+' = '+aa[kk]+'\n')
- success = True
- except:
- if DEBUG:
- print_exc()
- success = False
- try:
- r.close()
- except:
- pass
- return success
-
-
-if DEBUG:
- def errfunc(lineno, line, err):
- print '('+str(lineno)+') '+err+': '+line
-else:
- errfunc = lambda lineno, line, err: None
-
-def ini_read(f, errfunc = errfunc):
- try:
- r = open(f,'r')
- ll = r.readlines()
- d = {}
- dd = {'':d}
- for i in xrange(len(ll)):
- l = ll[i]
- l = l.strip()
- if not l:
- continue
- if l[0] == '#':
- continue
- if l[0] == '[':
- if l[-1] != ']':
- errfunc(i,l,'syntax error')
- continue
- l1 = l[1:-1].strip().lower()
- if not l1:
- errfunc(i,l,'syntax error')
- continue
- if dd.has_key(l1):
- errfunc(i,l,'duplicate section')
- d = dd[l1]
- continue
- d = {}
- dd[l1] = d
- continue
- try:
- k,v = l.split('=',1)
- except:
- try:
- k,v = l.split(':',1)
- except:
- errfunc(i,l,'syntax error')
- continue
- k = k.strip().lower()
- v = v.strip()
- if len(v) > 1 and ( (v[0] == '"' and v[-1] == '"') or
- (v[0] == "'" and v[-1] == "'") ):
- v = v[1:-1]
- if not k:
- errfunc(i,l,'syntax error')
- continue
- if d.has_key(k):
- errfunc(i,l,'duplicate entry')
- continue
- d[k] = v
- if DEBUG:
- print dd
- except:
- if DEBUG:
- print_exc()
- dd = None
- try:
- r.close()
- except:
- pass
- return dd
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from bisect import bisect, insort
-
-try:
- True
-except:
- True = 1
- False = 0
- bool = lambda x: not not x
-
-
-def to_long_ipv4(ip):
- ip = ip.split('.')
- if len(ip) != 4:
- raise ValueError, "bad address"
- b = 0L
- for n in ip:
- b *= 256
- b += int(n)
- return b
-
-
-def to_long_ipv6(ip):
- if ip == '':
- raise ValueError, "bad address"
- if ip == '::': # boundary handling
- ip = ''
- elif ip[:2] == '::':
- ip = ip[1:]
- elif ip[0] == ':':
- raise ValueError, "bad address"
- elif ip[-2:] == '::':
- ip = ip[:-1]
- elif ip[-1] == ':':
- raise ValueError, "bad address"
-
- b = []
- doublecolon = False
- for n in ip.split(':'):
- if n == '': # double-colon
- if doublecolon:
- raise ValueError, "bad address"
- doublecolon = True
- b.append(None)
- continue
- if n.find('.') >= 0: # IPv4
- n = n.split('.')
- if len(n) != 4:
- raise ValueError, "bad address"
- for i in n:
- b.append(int(i))
- continue
- n = ('0'*(4-len(n))) + n
- b.append(int(n[:2],16))
- b.append(int(n[2:],16))
- bb = 0L
- for n in b:
- if n is None:
- for i in xrange(17-len(b)):
- bb *= 256
- continue
- bb *= 256
- bb += n
- return bb
-
-ipv4addrmask = 65535L*256*256*256*256
-
-class IP_List:
- def __init__(self):
- self.ipv4list = [] # starts of ranges
- self.ipv4dict = {} # start: end of ranges
- self.ipv6list = [] # "
- self.ipv6dict = {} # "
-
- def __nonzero__(self):
- return bool(self.ipv4list or self.ipv6list)
-
-
- def append(self, ip_beg, ip_end = None):
- if ip_end is None:
- ip_end = ip_beg
- else:
- assert ip_beg <= ip_end
- if ip_beg.find(':') < 0: # IPv4
- ip_beg = to_long_ipv4(ip_beg)
- ip_end = to_long_ipv4(ip_end)
- l = self.ipv4list
- d = self.ipv4dict
- else:
- ip_beg = to_long_ipv6(ip_beg)
- ip_end = to_long_ipv6(ip_end)
- bb = ip_beg % (256*256*256*256)
- if bb == ipv4addrmask:
- ip_beg -= bb
- ip_end -= bb
- l = self.ipv4list
- d = self.ipv4dict
- else:
- l = self.ipv6list
- d = self.ipv6dict
-
- pos = bisect(l,ip_beg)-1
- done = pos < 0
- while not done:
- p = pos
- while p < len(l):
- range_beg = l[p]
- if range_beg > ip_end+1:
- done = True
- break
- range_end = d[range_beg]
- if range_end < ip_beg-1:
- p += 1
- if p == len(l):
- done = True
- break
- continue
- # if neither of the above conditions is true, the ranges overlap
- ip_beg = min(ip_beg, range_beg)
- ip_end = max(ip_end, range_end)
- del l[p]
- del d[range_beg]
- break
-
- insort(l,ip_beg)
- d[ip_beg] = ip_end
-
-
- def includes(self, ip):
- if not (self.ipv4list or self.ipv6list):
- return False
- if ip.find(':') < 0: # IPv4
- ip = to_long_ipv4(ip)
- l = self.ipv4list
- d = self.ipv4dict
- else:
- ip = to_long_ipv6(ip)
- bb = ip % (256*256*256*256)
- if bb == ipv4addrmask:
- ip -= bb
- l = self.ipv4list
- d = self.ipv4dict
- else:
- l = self.ipv6list
- d = self.ipv6dict
- for ip_beg in l[bisect(l,ip)-1:]:
- if ip == ip_beg:
- return True
- ip_end = d[ip_beg]
- if ip > ip_beg and ip <= ip_end:
- return True
- return False
-
-
- # reads a list from a file in the format 'whatever:whatever:ip-ip'
- # (not IPv6 compatible at all)
- def read_rangelist(self, file):
- f = open(file, 'r')
- while True:
- line = f.readline()
- if not line:
- break
- line = line.strip()
- if not line or line[0] == '#':
- continue
- line = line.split(':')[-1]
- try:
- ip1,ip2 = line.split('-')
- except:
- ip1 = line
- ip2 = line
- try:
- self.append(ip1.strip(),ip2.strip())
- except:
- print '*** WARNING *** could not parse IP range: '+line
- f.close()
-
-def is_ipv4(ip):
- return ip.find(':') < 0
-
-def is_valid_ip(ip):
- try:
- if is_ipv4(ip):
- a = ip.split('.')
- assert len(a) == 4
- for i in a:
- chr(int(i))
- return True
- to_long_ipv6(ip)
- return True
- except:
- return False
+++ /dev/null
-#!/usr/bin/env python
-
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from BitTornado import PSYCO
-if PSYCO.psyco:
- try:
- import psyco
- assert psyco.__version__ >= 0x010100f0
- psyco.full()
- except:
- pass
-
-from download_bt1 import BT1Download
-from RawServer import RawServer, UPnP_ERROR
-from RateLimiter import RateLimiter
-from ServerPortHandler import MultiHandler
-from parsedir import parsedir
-from natpunch import UPnP_test
-from random import seed
-from socket import error as socketerror
-from threading import Event
-from sys import argv, exit
-import sys, os
-from clock import clock
-from __init__ import createPeerID, mapbase64, version
-from cStringIO import StringIO
-from traceback import print_exc
-
-try:
- True
-except:
- True = 1
- False = 0
-
-
-def fmttime(n):
- try:
- n = int(n) # n may be None or too large
- assert n < 5184000 # 60 days
- except:
- return 'downloading'
- m, s = divmod(n, 60)
- h, m = divmod(m, 60)
- return '%d:%02d:%02d' % (h, m, s)
-
-class SingleDownload:
- def __init__(self, controller, hash, response, config, myid):
- self.controller = controller
- self.hash = hash
- self.response = response
- self.config = config
-
- self.doneflag = Event()
- self.waiting = True
- self.checking = False
- self.working = False
- self.seed = False
- self.closed = False
-
- self.status_msg = ''
- self.status_err = ['']
- self.status_errtime = 0
- self.status_done = 0.0
-
- self.rawserver = controller.handler.newRawServer(hash, self.doneflag)
-
- d = BT1Download(self.display, self.finished, self.error,
- controller.exchandler, self.doneflag, config, response,
- hash, myid, self.rawserver, controller.listen_port)
- self.d = d
-
- def start(self):
- if not self.d.saveAs(self.saveAs):
- self._shutdown()
- return
- self._hashcheckfunc = self.d.initFiles()
- if not self._hashcheckfunc:
- self._shutdown()
- return
- self.controller.hashchecksched(self.hash)
-
-
- def saveAs(self, name, length, saveas, isdir):
- return self.controller.saveAs(self.hash, name, saveas, isdir)
-
- def hashcheck_start(self, donefunc):
- if self.is_dead():
- self._shutdown()
- return
- self.waiting = False
- self.checking = True
- self._hashcheckfunc(donefunc)
-
- def hashcheck_callback(self):
- self.checking = False
- if self.is_dead():
- self._shutdown()
- return
- if not self.d.startEngine(ratelimiter = self.controller.ratelimiter):
- self._shutdown()
- return
- self.d.startRerequester()
- self.statsfunc = self.d.startStats()
- self.rawserver.start_listening(self.d.getPortHandler())
- self.working = True
-
- def is_dead(self):
- return self.doneflag.isSet()
-
- def _shutdown(self):
- self.shutdown(False)
-
- def shutdown(self, quiet=True):
- if self.closed:
- return
- self.doneflag.set()
- self.rawserver.shutdown()
- if self.checking or self.working:
- self.d.shutdown()
- self.waiting = False
- self.checking = False
- self.working = False
- self.closed = True
- self.controller.was_stopped(self.hash)
- if not quiet:
- self.controller.died(self.hash)
-
-
- def display(self, activity = None, fractionDone = None):
- # really only used by StorageWrapper now
- if activity:
- self.status_msg = activity
- if fractionDone is not None:
- self.status_done = float(fractionDone)
-
- def finished(self):
- self.seed = True
-
- def error(self, msg):
- if self.doneflag.isSet():
- self._shutdown()
- self.status_err.append(msg)
- self.status_errtime = clock()
-
-
-class LaunchMany:
- def __init__(self, config, Output):
- try:
- self.config = config
- self.Output = Output
-
- self.torrent_dir = config['torrent_dir']
- self.torrent_cache = {}
- self.file_cache = {}
- self.blocked_files = {}
- self.scan_period = config['parse_dir_interval']
- self.stats_period = config['display_interval']
-
- self.torrent_list = []
- self.downloads = {}
- self.counter = 0
- self.doneflag = Event()
-
- self.hashcheck_queue = []
- self.hashcheck_current = None
-
- self.rawserver = RawServer(self.doneflag, config['timeout_check_interval'],
- config['timeout'], ipv6_enable = config['ipv6_enabled'],
- failfunc = self.failed, errorfunc = self.exchandler)
- upnp_type = UPnP_test(config['upnp_nat_access'])
- while True:
- try:
- self.listen_port = self.rawserver.find_and_bind(
- config['minport'], config['maxport'], config['bind'],
- ipv6_socket_style = config['ipv6_binds_v4'],
- upnp = upnp_type, randomizer = config['random_port'])
- break
- except socketerror, e:
- if upnp_type and e == UPnP_ERROR:
- self.Output.message('WARNING: COULD NOT FORWARD VIA UPnP')
- upnp_type = 0
- continue
- self.failed("Couldn't listen - " + str(e))
- return
-
- self.ratelimiter = RateLimiter(self.rawserver.add_task,
- config['upload_unit_size'])
- self.ratelimiter.set_upload_rate(config['max_upload_rate'])
-
- self.handler = MultiHandler(self.rawserver, self.doneflag)
- seed(createPeerID())
- self.rawserver.add_task(self.scan, 0)
- self.rawserver.add_task(self.stats, 0)
-
- self.handler.listen_forever()
-
- self.Output.message('shutting down')
- self.hashcheck_queue = []
- for hash in self.torrent_list:
- self.Output.message('dropped "'+self.torrent_cache[hash]['path']+'"')
- self.downloads[hash].shutdown()
- self.rawserver.shutdown()
-
- except:
- data = StringIO()
- print_exc(file = data)
- Output.exception(data.getvalue())
-
-
- def scan(self):
- self.rawserver.add_task(self.scan, self.scan_period)
-
- r = parsedir(self.torrent_dir, self.torrent_cache,
- self.file_cache, self.blocked_files,
- return_metainfo = True, errfunc = self.Output.message)
-
- ( self.torrent_cache, self.file_cache, self.blocked_files,
- added, removed ) = r
-
- for hash, data in removed.items():
- self.Output.message('dropped "'+data['path']+'"')
- self.remove(hash)
- for hash, data in added.items():
- self.Output.message('added "'+data['path']+'"')
- self.add(hash, data)
-
- def stats(self):
- self.rawserver.add_task(self.stats, self.stats_period)
- data = []
- for hash in self.torrent_list:
- cache = self.torrent_cache[hash]
- if self.config['display_path']:
- name = cache['path']
- else:
- name = cache['name']
- size = cache['length']
- d = self.downloads[hash]
- progress = '0.0%'
- peers = 0
- seeds = 0
- seedsmsg = "S"
- dist = 0.0
- uprate = 0.0
- dnrate = 0.0
- upamt = 0
- dnamt = 0
- t = 0
- if d.is_dead():
- status = 'stopped'
- elif d.waiting:
- status = 'waiting for hash check'
- elif d.checking:
- status = d.status_msg
- progress = '%.1f%%' % (d.status_done*100)
- else:
- stats = d.statsfunc()
- s = stats['stats']
- if d.seed:
- status = 'seeding'
- progress = '100.0%'
- seeds = s.numOldSeeds
- seedsmsg = "s"
- dist = s.numCopies
- else:
- if s.numSeeds + s.numPeers:
- t = stats['time']
- if t == 0: # unlikely
- t = 0.01
- status = fmttime(t)
- else:
- t = -1
- status = 'connecting to peers'
- progress = '%.1f%%' % (int(stats['frac']*1000)/10.0)
- seeds = s.numSeeds
- dist = s.numCopies2
- dnrate = stats['down']
- peers = s.numPeers
- uprate = stats['up']
- upamt = s.upTotal
- dnamt = s.downTotal
-
- if d.is_dead() or d.status_errtime+300 > clock():
- msg = d.status_err[-1]
- else:
- msg = ''
-
- data.append(( name, status, progress, peers, seeds, seedsmsg, dist,
- uprate, dnrate, upamt, dnamt, size, t, msg ))
- stop = self.Output.display(data)
- if stop:
- self.doneflag.set()
-
- def remove(self, hash):
- self.torrent_list.remove(hash)
- self.downloads[hash].shutdown()
- del self.downloads[hash]
-
- def add(self, hash, data):
- c = self.counter
- self.counter += 1
- x = ''
- for i in xrange(3):
- x = mapbase64[c & 0x3F]+x
- c >>= 6
- peer_id = createPeerID(x)
- d = SingleDownload(self, hash, data['metainfo'], self.config, peer_id)
- self.torrent_list.append(hash)
- self.downloads[hash] = d
- d.start()
-
-
- def saveAs(self, hash, name, saveas, isdir):
- x = self.torrent_cache[hash]
- style = self.config['saveas_style']
- if style == 1 or style == 3:
- if saveas:
- saveas = os.path.join(saveas,x['file'][:-1-len(x['type'])])
- else:
- saveas = x['path'][:-1-len(x['type'])]
- if style == 3:
- if not os.path.isdir(saveas):
- try:
- os.mkdir(saveas)
- except:
- raise OSError("couldn't create directory for "+x['path']
- +" ("+saveas+")")
- if not isdir:
- saveas = os.path.join(saveas, name)
- else:
- if saveas:
- saveas = os.path.join(saveas, name)
- else:
- saveas = os.path.join(os.path.split(x['path'])[0], name)
-
- if isdir and not os.path.isdir(saveas):
- try:
- os.mkdir(saveas)
- except:
- raise OSError("couldn't create directory for "+x['path']
- +" ("+saveas+")")
- return saveas
-
-
- def hashchecksched(self, hash = None):
- if hash:
- self.hashcheck_queue.append(hash)
- if not self.hashcheck_current:
- self._hashcheck_start()
-
- def _hashcheck_start(self):
- self.hashcheck_current = self.hashcheck_queue.pop(0)
- self.downloads[self.hashcheck_current].hashcheck_start(self.hashcheck_callback)
-
- def hashcheck_callback(self):
- self.downloads[self.hashcheck_current].hashcheck_callback()
- if self.hashcheck_queue:
- self._hashcheck_start()
- else:
- self.hashcheck_current = None
-
- def died(self, hash):
- if self.torrent_cache.has_key(hash):
- self.Output.message('DIED: "'+self.torrent_cache[hash]['path']+'"')
-
- def was_stopped(self, hash):
- try:
- self.hashcheck_queue.remove(hash)
- except:
- pass
- if self.hashcheck_current == hash:
- self.hashcheck_current = None
- if self.hashcheck_queue:
- self._hashcheck_start()
-
- def failed(self, s):
- self.Output.message('FAILURE: '+s)
-
- def exchandler(self, s):
- self.Output.exception(s)
+++ /dev/null
-# Written by John Hoffman
-# derived from NATPortMapping.py by Yejun Yang
-# and from example code by Myers Carpenter
-# see LICENSE.txt for license information
-
-import socket
-from traceback import print_exc
-from subnetparse import IP_List
-from clock import clock
-from __init__ import createPeerID
-try:
- True
-except:
- True = 1
- False = 0
-
-DEBUG = False
-
-EXPIRE_CACHE = 30 # seconds
-ID = "BT-"+createPeerID()[-4:]
-
-try:
- import pythoncom, win32com.client
- _supported = 1
-except ImportError:
- _supported = 0
-
-
-
-class _UPnP1: # derived from Myers Carpenter's code
- # seems to use the machine's local UPnP
- # system for its operation. Runs fairly fast
-
- def __init__(self):
- self.map = None
- self.last_got_map = -10e10
-
- def _get_map(self):
- if self.last_got_map + EXPIRE_CACHE < clock():
- try:
- dispatcher = win32com.client.Dispatch("HNetCfg.NATUPnP")
- self.map = dispatcher.StaticPortMappingCollection
- self.last_got_map = clock()
- except:
- self.map = None
- return self.map
-
- def test(self):
- try:
- assert self._get_map() # make sure a map was found
- success = True
- except:
- success = False
- return success
-
-
- def open(self, ip, p):
- map = self._get_map()
- try:
- map.Add(p,'TCP',p,ip,True,ID)
- if DEBUG:
- print 'port opened: '+ip+':'+str(p)
- success = True
- except:
- if DEBUG:
- print "COULDN'T OPEN "+str(p)
- print_exc()
- success = False
- return success
-
-
- def close(self, p):
- map = self._get_map()
- try:
- map.Remove(p,'TCP')
- success = True
- if DEBUG:
- print 'port closed: '+str(p)
- except:
- if DEBUG:
- print 'ERROR CLOSING '+str(p)
- print_exc()
- success = False
- return success
-
-
- def clean(self, retry = False):
- if not _supported:
- return
- try:
- map = self._get_map()
- ports_in_use = []
- for i in xrange(len(map)):
- try:
- mapping = map[i]
- port = mapping.ExternalPort
- prot = str(mapping.Protocol).lower()
- desc = str(mapping.Description).lower()
- except:
- port = None
- if port and prot == 'tcp' and desc[:3] == 'bt-':
- ports_in_use.append(port)
- success = True
- for port in ports_in_use:
- try:
- map.Remove(port,'TCP')
- except:
- success = False
- if not success and not retry:
- self.clean(retry = True)
- except:
- pass
-
-
-class _UPnP2: # derived from Yejun Yang's code
- # apparently does a direct search for UPnP hardware
- # may work in some cases where _UPnP1 won't, but is slow
- # still need to implement "clean" method
-
- def __init__(self):
- self.services = None
- self.last_got_services = -10e10
-
- def _get_services(self):
- if not self.services or self.last_got_services + EXPIRE_CACHE < clock():
- self.services = []
- try:
- f=win32com.client.Dispatch("UPnP.UPnPDeviceFinder")
- for t in ( "urn:schemas-upnp-org:service:WANIPConnection:1",
- "urn:schemas-upnp-org:service:WANPPPConnection:1" ):
- try:
- conns = f.FindByType(t,0)
- for c in xrange(len(conns)):
- try:
- svcs = conns[c].Services
- for s in xrange(len(svcs)):
- try:
- self.services.append(svcs[s])
- except:
- pass
- except:
- pass
- except:
- pass
- except:
- pass
- self.last_got_services = clock()
- return self.services
-
- def test(self):
- try:
- assert self._get_services() # make sure some services can be found
- success = True
- except:
- success = False
- return success
-
-
- def open(self, ip, p):
- svcs = self._get_services()
- success = False
- for s in svcs:
- try:
- s.InvokeAction('AddPortMapping',['',p,'TCP',p,ip,True,ID,0],'')
- success = True
- except:
- pass
- if DEBUG and not success:
- print "COULDN'T OPEN "+str(p)
- print_exc()
- return success
-
-
- def close(self, p):
- svcs = self._get_services()
- success = False
- for s in svcs:
- try:
- s.InvokeAction('DeletePortMapping', ['',p,'TCP'], '')
- success = True
- except:
- pass
- if DEBUG and not success:
- print "COULDN'T OPEN "+str(p)
- print_exc()
- return success
-
-
-class _UPnP: # master holding class
- def __init__(self):
- self.upnp1 = _UPnP1()
- self.upnp2 = _UPnP2()
- self.upnplist = (None, self.upnp1, self.upnp2)
- self.upnp = None
- self.local_ip = None
- self.last_got_ip = -10e10
-
- def get_ip(self):
- if self.last_got_ip + EXPIRE_CACHE < clock():
- local_ips = IP_List()
- local_ips.set_intranet_addresses()
- try:
- for info in socket.getaddrinfo(socket.gethostname(),0,socket.AF_INET):
- # exception if socket library isn't recent
- self.local_ip = info[4][0]
- if local_ips.includes(self.local_ip):
- self.last_got_ip = clock()
- if DEBUG:
- print 'Local IP found: '+self.local_ip
- break
- else:
- raise ValueError('couldn\'t find intranet IP')
- except:
- self.local_ip = None
- if DEBUG:
- print 'Error finding local IP'
- print_exc()
- return self.local_ip
-
- def test(self, upnp_type):
- if DEBUG:
- print 'testing UPnP type '+str(upnp_type)
- if not upnp_type or not _supported or self.get_ip() is None:
- if DEBUG:
- print 'not supported'
- return 0
- pythoncom.CoInitialize() # leave initialized
- self.upnp = self.upnplist[upnp_type] # cache this
- if self.upnp.test():
- if DEBUG:
- print 'ok'
- return upnp_type
- if DEBUG:
- print 'tested bad'
- return 0
-
- def open(self, p):
- assert self.upnp, "must run UPnP_test() with the desired UPnP access type first"
- return self.upnp.open(self.get_ip(), p)
-
- def close(self, p):
- assert self.upnp, "must run UPnP_test() with the desired UPnP access type first"
- return self.upnp.close(p)
-
- def clean(self):
- return self.upnp1.clean()
-
-_upnp_ = _UPnP()
-
-UPnP_test = _upnp_.test
-UPnP_open_port = _upnp_.open
-UPnP_close_port = _upnp_.close
-UPnP_reset = _upnp_.clean
-
+++ /dev/null
-# Written by Bill Bumgarner and Bram Cohen
-# see LICENSE.txt for license information
-
-from types import *
-from cStringIO import StringIO
-
-
-def splitLine(line, COLS=80, indent=10):
- indent = " " * indent
- width = COLS - (len(indent) + 1)
- if indent and width < 15:
- width = COLS - 2
- indent = " "
- s = StringIO()
- i = 0
- for word in line.split():
- if i == 0:
- s.write(indent+word)
- i = len(word)
- continue
- if i + len(word) >= width:
- s.write('\n'+indent+word)
- i = len(word)
- continue
- s.write(' '+word)
- i += len(word) + 1
- return s.getvalue()
-
-def formatDefinitions(options, COLS, presets = {}):
- s = StringIO()
- for (longname, default, doc) in options:
- s.write('--' + longname + ' <arg>\n')
- default = presets.get(longname, default)
- if type(default) in (IntType, LongType):
- try:
- default = int(default)
- except:
- pass
- if default is not None:
- doc += ' (defaults to ' + repr(default) + ')'
- s.write(splitLine(doc,COLS,10))
- s.write('\n\n')
- return s.getvalue()
-
-
-def usage(str):
- raise ValueError(str)
-
-
-def defaultargs(options):
- l = {}
- for (longname, default, doc) in options:
- if default is not None:
- l[longname] = default
- return l
-
-
-def parseargs(argv, options, minargs = None, maxargs = None, presets = {}):
- config = {}
- longkeyed = {}
- for option in options:
- longname, default, doc = option
- longkeyed[longname] = option
- config[longname] = default
- for longname in presets.keys(): # presets after defaults but before arguments
- config[longname] = presets[longname]
- options = []
- args = []
- pos = 0
- while pos < len(argv):
- if argv[pos][:2] != '--':
- args.append(argv[pos])
- pos += 1
- else:
- if pos == len(argv) - 1:
- usage('parameter passed in at end with no value')
- key, value = argv[pos][2:], argv[pos+1]
- pos += 2
- if not longkeyed.has_key(key):
- usage('unknown key --' + key)
- longname, default, doc = longkeyed[key]
- try:
- t = type(config[longname])
- if t is NoneType or t is StringType:
- config[longname] = value
- elif t in (IntType, LongType):
- config[longname] = long(value)
- elif t is FloatType:
- config[longname] = float(value)
- else:
- assert 0
- except ValueError, e:
- usage('wrong format of --%s - %s' % (key, str(e)))
- for key, value in config.items():
- if value is None:
- usage("Option --%s is required." % key)
- if minargs is not None and len(args) < minargs:
- usage("Must supply at least %d args." % minargs)
- if maxargs is not None and len(args) > maxargs:
- usage("Too many args - %d max." % maxargs)
- return (config, args)
-
-def test_parseargs():
- assert parseargs(('d', '--a', 'pq', 'e', '--b', '3', '--c', '4.5', 'f'), (('a', 'x', ''), ('b', 1, ''), ('c', 2.3, ''))) == ({'a': 'pq', 'b': 3, 'c': 4.5}, ['d', 'e', 'f'])
- assert parseargs([], [('a', 'x', '')]) == ({'a': 'x'}, [])
- assert parseargs(['--a', 'x', '--a', 'y'], [('a', '', '')]) == ({'a': 'y'}, [])
- try:
- parseargs([], [('a', 'x', '')])
- except ValueError:
- pass
- try:
- parseargs(['--a', 'x'], [])
- except ValueError:
- pass
- try:
- parseargs(['--a'], [('a', 'x', '')])
- except ValueError:
- pass
- try:
- parseargs([], [], 1, 2)
- except ValueError:
- pass
- assert parseargs(['x'], [], 1, 2) == ({}, ['x'])
- assert parseargs(['x', 'y'], [], 1, 2) == ({}, ['x', 'y'])
- try:
- parseargs(['x', 'y', 'z'], [], 1, 2)
- except ValueError:
- pass
- try:
- parseargs(['--a', '2.0'], [('a', 3, '')])
- except ValueError:
- pass
- try:
- parseargs(['--a', 'z'], [('a', 2.1, '')])
- except ValueError:
- pass
-
+++ /dev/null
-# Written by John Hoffman and Uoti Urpala
-# see LICENSE.txt for license information
-from bencode import bencode, bdecode
-from BT1.btformats import check_info
-from os.path import exists, isfile
-from sha import sha
-import sys, os
-
-try:
- True
-except:
- True = 1
- False = 0
-
-NOISY = False
-
-def _errfunc(x):
- print ":: "+x
-
-def parsedir(directory, parsed, files, blocked,
- exts = ['.torrent'], return_metainfo = False, errfunc = _errfunc):
- if NOISY:
- errfunc('checking dir')
- dirs_to_check = [directory]
- new_files = {}
- new_blocked = {}
- torrent_type = {}
- while dirs_to_check: # first, recurse directories and gather torrents
- directory = dirs_to_check.pop()
- newtorrents = False
- for f in os.listdir(directory):
- newtorrent = None
- for ext in exts:
- if f.endswith(ext):
- newtorrent = ext[1:]
- break
- if newtorrent:
- newtorrents = True
- p = os.path.join(directory, f)
- new_files[p] = [(os.path.getmtime(p), os.path.getsize(p)), 0]
- torrent_type[p] = newtorrent
- if not newtorrents:
- for f in os.listdir(directory):
- p = os.path.join(directory, f)
- if os.path.isdir(p):
- dirs_to_check.append(p)
-
- new_parsed = {}
- to_add = []
- added = {}
- removed = {}
- # files[path] = [(modification_time, size), hash], hash is 0 if the file
- # has not been successfully parsed
- for p,v in new_files.items(): # re-add old items and check for changes
- oldval = files.get(p)
- if not oldval: # new file
- to_add.append(p)
- continue
- h = oldval[1]
- if oldval[0] == v[0]: # file is unchanged from last parse
- if h:
- if blocked.has_key(p): # parseable + blocked means duplicate
- to_add.append(p) # other duplicate may have gone away
- else:
- new_parsed[h] = parsed[h]
- new_files[p] = oldval
- else:
- new_blocked[p] = 1 # same broken unparseable file
- continue
- if parsed.has_key(h) and not blocked.has_key(p):
- if NOISY:
- errfunc('removing '+p+' (will re-add)')
- removed[h] = parsed[h]
- to_add.append(p)
-
- to_add.sort()
- for p in to_add: # then, parse new and changed torrents
- new_file = new_files[p]
- v,h = new_file
- if new_parsed.has_key(h): # duplicate
- if not blocked.has_key(p) or files[p][0] != v:
- errfunc('**warning** '+
- p +' is a duplicate torrent for '+new_parsed[h]['path'])
- new_blocked[p] = 1
- continue
-
- if NOISY:
- errfunc('adding '+p)
- try:
- ff = open(p, 'rb')
- d = bdecode(ff.read())
- check_info(d['info'])
- h = sha(bencode(d['info'])).digest()
- new_file[1] = h
- if new_parsed.has_key(h):
- errfunc('**warning** '+
- p +' is a duplicate torrent for '+new_parsed[h]['path'])
- new_blocked[p] = 1
- continue
-
- a = {}
- a['path'] = p
- f = os.path.basename(p)
- a['file'] = f
- a['type'] = torrent_type[p]
- i = d['info']
- l = 0
- nf = 0
- if i.has_key('length'):
- l = i.get('length',0)
- nf = 1
- elif i.has_key('files'):
- for li in i['files']:
- nf += 1
- if li.has_key('length'):
- l += li['length']
- a['numfiles'] = nf
- a['length'] = l
- a['name'] = i.get('name', f)
- def setkey(k, d = d, a = a):
- if d.has_key(k):
- a[k] = d[k]
- setkey('failure reason')
- setkey('warning message')
- setkey('announce-list')
- if return_metainfo:
- a['metainfo'] = d
- except:
- errfunc('**warning** '+p+' has errors')
- new_blocked[p] = 1
- continue
- try:
- ff.close()
- except:
- pass
- if NOISY:
- errfunc('... successful')
- new_parsed[h] = a
- added[h] = a
-
- for p,v in files.items(): # and finally, mark removed torrents
- if not new_files.has_key(p) and not blocked.has_key(p):
- if NOISY:
- errfunc('removing '+p)
- removed[v[1]] = parsed[v[1]]
-
- if NOISY:
- errfunc('done checking')
- return (new_parsed, new_files, new_blocked, added, removed)
-
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from array import array
-from threading import Lock
-# import inspect
-try:
- True
-except:
- True = 1
- False = 0
-
-DEBUG = False
-
-class SingleBuffer:
- def __init__(self, pool):
- self.pool = pool
- self.buf = array('c')
-
- def init(self):
- if DEBUG:
- print self.count
- '''
- for x in xrange(6,1,-1):
- try:
- f = inspect.currentframe(x).f_code
- print (f.co_filename,f.co_firstlineno,f.co_name)
- del f
- except:
- pass
- print ''
- '''
- self.length = 0
-
- def append(self, s):
- l = self.length+len(s)
- self.buf[self.length:l] = array('c',s)
- self.length = l
-
- def __len__(self):
- return self.length
-
- def __getslice__(self, a, b):
- if b > self.length:
- b = self.length
- if b < 0:
- b += self.length
- if a == 0 and b == self.length and len(self.buf) == b:
- return self.buf # optimization
- return self.buf[a:b]
-
- def getarray(self):
- return self.buf[:self.length]
-
- def release(self):
- if DEBUG:
- print -self.count
- self.pool.release(self)
-
-
-class BufferPool:
- def __init__(self):
- self.pool = []
- self.lock = Lock()
- if DEBUG:
- self.count = 0
-
- def new(self):
- self.lock.acquire()
- if self.pool:
- x = self.pool.pop()
- else:
- x = SingleBuffer(self)
- if DEBUG:
- self.count += 1
- x.count = self.count
- x.init()
- self.lock.release()
- return x
-
- def release(self, x):
- self.pool.append(x)
-
-
-_pool = BufferPool()
-PieceBuffer = _pool.new
+++ /dev/null
-# Written by Bram Cohen
-# see LICENSE.txt for license information
-
-from select import select, error
-from time import sleep
-from types import IntType
-from bisect import bisect
-POLLIN = 1
-POLLOUT = 2
-POLLERR = 8
-POLLHUP = 16
-
-class poll:
- def __init__(self):
- self.rlist = []
- self.wlist = []
-
- def register(self, f, t):
- if type(f) != IntType:
- f = f.fileno()
- if (t & POLLIN):
- insert(self.rlist, f)
- else:
- remove(self.rlist, f)
- if (t & POLLOUT):
- insert(self.wlist, f)
- else:
- remove(self.wlist, f)
-
- def unregister(self, f):
- if type(f) != IntType:
- f = f.fileno()
- remove(self.rlist, f)
- remove(self.wlist, f)
-
- def poll(self, timeout = None):
- if self.rlist or self.wlist:
- try:
- r, w, e = select(self.rlist, self.wlist, [], timeout)
- except ValueError:
- return None
- else:
- sleep(timeout)
- return []
- result = []
- for s in r:
- result.append((s, POLLIN))
- for s in w:
- result.append((s, POLLOUT))
- return result
-
-def remove(list, item):
- i = bisect(list, item)
- if i > 0 and list[i-1] == item:
- del list[i-1]
-
-def insert(list, item):
- i = bisect(list, item)
- if i == 0 or list[i-1] != item:
- list.insert(i, item)
-
-def test_remove():
- x = [2, 4, 6]
- remove(x, 2)
- assert x == [4, 6]
- x = [2, 4, 6]
- remove(x, 4)
- assert x == [2, 6]
- x = [2, 4, 6]
- remove(x, 6)
- assert x == [2, 4]
- x = [2, 4, 6]
- remove(x, 5)
- assert x == [2, 4, 6]
- x = [2, 4, 6]
- remove(x, 1)
- assert x == [2, 4, 6]
- x = [2, 4, 6]
- remove(x, 7)
- assert x == [2, 4, 6]
- x = [2, 4, 6]
- remove(x, 5)
- assert x == [2, 4, 6]
- x = []
- remove(x, 3)
- assert x == []
-
-def test_insert():
- x = [2, 4]
- insert(x, 1)
- assert x == [1, 2, 4]
- x = [2, 4]
- insert(x, 3)
- assert x == [2, 3, 4]
- x = [2, 4]
- insert(x, 5)
- assert x == [2, 4, 5]
- x = [2, 4]
- insert(x, 2)
- assert x == [2, 4]
- x = [2, 4]
- insert(x, 4)
- assert x == [2, 4]
- x = [2, 3, 4]
- insert(x, 3)
- assert x == [2, 3, 4]
- x = []
- insert(x, 3)
- assert x == [3]
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from bisect import bisect, insort
-
-try:
- True
-except:
- True = 1
- False = 0
- bool = lambda x: not not x
-
-hexbinmap = {
- '0': '0000',
- '1': '0001',
- '2': '0010',
- '3': '0011',
- '4': '0100',
- '5': '0101',
- '6': '0110',
- '7': '0111',
- '8': '1000',
- '9': '1001',
- 'a': '1010',
- 'b': '1011',
- 'c': '1100',
- 'd': '1101',
- 'e': '1110',
- 'f': '1111',
- 'x': '0000',
-}
-
-chrbinmap = {}
-for n in xrange(256):
- b = []
- nn = n
- for i in xrange(8):
- if nn & 0x80:
- b.append('1')
- else:
- b.append('0')
- nn <<= 1
- chrbinmap[n] = ''.join(b)
-
-
-def to_bitfield_ipv4(ip):
- ip = ip.split('.')
- if len(ip) != 4:
- raise ValueError, "bad address"
- b = []
- for i in ip:
- b.append(chrbinmap[int(i)])
- return ''.join(b)
-
-def to_bitfield_ipv6(ip):
- b = ''
- doublecolon = False
-
- if ip == '':
- raise ValueError, "bad address"
- if ip == '::': # boundary handling
- ip = ''
- elif ip[:2] == '::':
- ip = ip[1:]
- elif ip[0] == ':':
- raise ValueError, "bad address"
- elif ip[-2:] == '::':
- ip = ip[:-1]
- elif ip[-1] == ':':
- raise ValueError, "bad address"
- for n in ip.split(':'):
- if n == '': # double-colon
- if doublecolon:
- raise ValueError, "bad address"
- doublecolon = True
- b += ':'
- continue
- if n.find('.') >= 0: # IPv4
- n = to_bitfield_ipv4(n)
- b += n + '0'*(32-len(n))
- continue
- n = ('x'*(4-len(n))) + n
- for i in n:
- b += hexbinmap[i]
- if doublecolon:
- pos = b.find(':')
- b = b[:pos]+('0'*(129-len(b)))+b[pos+1:]
- if len(b) != 128: # always check size
- raise ValueError, "bad address"
- return b
-
-ipv4addrmask = to_bitfield_ipv6('::ffff:0:0')[:96]
-
-class IP_List:
- def __init__(self):
- self.ipv4list = []
- self.ipv6list = []
-
- def __nonzero__(self):
- return bool(self.ipv4list or self.ipv6list)
-
-
- def append(self, ip, depth = 256):
- if ip.find(':') < 0: # IPv4
- insort(self.ipv4list,to_bitfield_ipv4(ip)[:depth])
- else:
- b = to_bitfield_ipv6(ip)
- if b.startswith(ipv4addrmask):
- insort(self.ipv4list,b[96:][:depth-96])
- else:
- insort(self.ipv6list,b[:depth])
-
-
- def includes(self, ip):
- if not (self.ipv4list or self.ipv6list):
- return False
- if ip.find(':') < 0: # IPv4
- b = to_bitfield_ipv4(ip)
- else:
- b = to_bitfield_ipv6(ip)
- if b.startswith(ipv4addrmask):
- b = b[96:]
- if len(b) > 32:
- l = self.ipv6list
- else:
- l = self.ipv4list
- for map in l[bisect(l,b)-1:]:
- if b.startswith(map):
- return True
- if map > b:
- return False
- return False
-
-
- def read_fieldlist(self, file): # reads a list from a file in the format 'ip/len <whatever>'
- f = open(file, 'r')
- while True:
- line = f.readline()
- if not line:
- break
- line = line.strip().expandtabs()
- if not line or line[0] == '#':
- continue
- try:
- line, garbage = line.split(' ',1)
- except:
- pass
- try:
- line, garbage = line.split('#',1)
- except:
- pass
- try:
- ip, depth = line.split('/')
- except:
- ip = line
- depth = None
- try:
- if depth is not None:
- depth = int(depth)
- self.append(ip,depth)
- except:
- print '*** WARNING *** could not parse IP range: '+line
- f.close()
-
-
- def set_intranet_addresses(self):
- self.append('127.0.0.1',8)
- self.append('10.0.0.0',8)
- self.append('172.16.0.0',12)
- self.append('192.168.0.0',16)
- self.append('169.254.0.0',16)
- self.append('::1')
- self.append('fe80::',16)
- self.append('fec0::',16)
-
- def set_ipv4_addresses(self):
- self.append('::ffff:0:0',96)
-
-def ipv6_to_ipv4(ip):
- ip = to_bitfield_ipv6(ip)
- if not ip.startswith(ipv4addrmask):
- raise ValueError, "not convertible to IPv4"
- ip = ip[-32:]
- x = ''
- for i in range(4):
- x += str(int(ip[:8],2))
- if i < 3:
- x += '.'
- ip = ip[8:]
- return x
-
-def to_ipv4(ip):
- if is_ipv4(ip):
- _valid_ipv4(ip)
- return ip
- return ipv6_to_ipv4(ip)
-
-def is_ipv4(ip):
- return ip.find(':') < 0
-
-def _valid_ipv4(ip):
- ip = ip.split('.')
- if len(ip) != 4:
- raise ValueError
- for i in ip:
- chr(int(i))
-
-def is_valid_ip(ip):
- try:
- if not ip:
- return False
- if is_ipv4(ip):
- _valid_ipv4(ip)
- return True
- to_bitfield_ipv6(ip)
- return True
- except:
- return False
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from binascii import unhexlify
-
-try:
- True
-except:
- True = 1
- False = 0
-
-
-# parses a list of torrent hashes, in the format of one hash per line in hex format
-
-def parsetorrentlist(filename, parsed):
- new_parsed = {}
- added = {}
- removed = parsed
- f = open(filename, 'r')
- while True:
- l = f.readline()
- if not l:
- break
- l = l.strip()
- try:
- if len(l) != 40:
- raise ValueError, 'bad line'
- h = unhexlify(l)
- except:
- print '*** WARNING *** could not parse line in torrent list: '+l
- if parsed.has_key(h):
- del removed[h]
- else:
- added[h] = True
- new_parsed[h] = True
- f.close()
- return (new_parsed, added, removed)
-
+++ /dev/null
-# Written by John Hoffman
-# see LICENSE.txt for license information
-
-from httplib import HTTPConnection, HTTPSConnection, HTTPException
-from urlparse import urlparse
-from bencode import bdecode
-import socket
-from gzip import GzipFile
-from StringIO import StringIO
-from urllib import quote, unquote
-from __init__ import product_name, version_short
-
-VERSION = product_name+'/'+version_short
-MAX_REDIRECTS = 10
-
-
-class btHTTPcon(HTTPConnection): # attempt to add automatic connection timeout
- def connect(self):
- HTTPConnection.connect(self)
- try:
- self.sock.settimeout(30)
- except:
- pass
-
-class btHTTPScon(HTTPSConnection): # attempt to add automatic connection timeout
- def connect(self):
- HTTPSConnection.connect(self)
- try:
- self.sock.settimeout(30)
- except:
- pass
-
-class urlopen:
- def __init__(self, url):
- self.tries = 0
- self._open(url.strip())
- self.error_return = None
-
- def _open(self, url):
- self.tries += 1
- if self.tries > MAX_REDIRECTS:
- raise IOError, ('http error', 500,
- "Internal Server Error: Redirect Recursion")
- (scheme, netloc, path, pars, query, fragment) = urlparse(url)
- if scheme != 'http' and scheme != 'https':
- raise IOError, ('url error', 'unknown url type', scheme, url)
- url = path
- if pars:
- url += ';'+pars
- if query:
- url += '?'+query
-# if fragment:
- try:
- if scheme == 'http':
- self.connection = btHTTPcon(netloc)
- else:
- self.connection = btHTTPScon(netloc)
- self.connection.request('GET', url, None,
- { 'User-Agent': VERSION,
- 'Accept-Encoding': 'gzip' } )
- self.response = self.connection.getresponse()
- except HTTPException, e:
- raise IOError, ('http error', str(e))
- status = self.response.status
- if status in (301,302):
- try:
- self.connection.close()
- except:
- pass
- self._open(self.response.getheader('Location'))
- return
- if status != 200:
- try:
- data = self._read()
- d = bdecode(data)
- if d.has_key('failure reason'):
- self.error_return = data
- return
- except:
- pass
- raise IOError, ('http error', status, self.response.reason)
-
- def read(self):
- if self.error_return:
- return self.error_return
- return self._read()
-
- def _read(self):
- data = self.response.read()
- if self.response.getheader('Content-Encoding','').find('gzip') >= 0:
- try:
- compressed = StringIO(data)
- f = GzipFile(fileobj = compressed)
- data = f.read()
- except:
- raise IOError, ('http error', 'got corrupt response')
- return data
-
- def close(self):
- self.connection.close()
+++ /dev/null
-#!/usr/bin/python
-
-import os
-
-import web
-import web.elements
-from web.javascript import Javascript
-
-BASE="/srv/checkout"
-
-projects = []
-
-class Po(object):
- code2lang = {
- "da" : "Dansk (Dansk)",
- "de" : "Deutsch (German)",
- "fr" : "Français (French)",
- }
-
- def __init__(self, path):
- self.path = path
-
- p = os.popen("msgfmt -v --statistics %s 2>&1" % self.path)
- self.line = p.readlines()[0]
-
- def __cmp__(self, other):
- return cmp(self.lang, other.lang)
-
- @property
- def code(self):
- return os.path.basename(self.path)[:-3]
-
- @property
- def lang(self):
- return self.code2lang.get(self.code, "Unknown (%s)" % self.code)
-
- @property
- def translated(self):
- return int(self.line.split()[0])
-
- @property
- def untranslated(self):
- l = self.line.split()
- if len(l) == 6:
- return int(l[3])
- elif len(l) == 9:
- return int(l[6])
- return 0
-
- @property
- def fuzzy(self):
- l = self.line.split()
- if len(l) == 9:
- return l[3]
- return 0
-
-
-class Project(object):
- def __init__(self, id, path, **kwargs):
- self.id = id
- self.path = path
- self._name = kwargs.pop("name")
- self.desc = kwargs.pop("desc")
-
- self._translations = []
- self.pot = None
- self.find_pot()
-
- @property
- def name(self):
- if self._name:
- return self._name
- return self.id
-
- @property
- def translations(self):
- if not self._translations:
- for path in os.listdir(self.path):
- if path.endswith(".po"):
- self._translations.append(Po(os.path.join(self.path, path)))
- return self._translations
-
- def find_pot(self):
- for path in os.listdir(self.path):
- if path.endswith(".pot"):
- self.pot = Po(os.path.join(self.path, path))
- break
-
-
-projects.append(Project("pomona", BASE + "/ipfire-3.x/src/pomona/po", name="Pomona", desc="The pomona installer for ipfire."))
-
-class Content(web.Content):
- def __init__(self):
- web.Content.__init__(self)
- self.projects = projects
-
- def __call__(self, lang):
- ret = """<h3>IPFire Translation Status</h3>
- <div id="tabs"><ul>"""
-
- for project in self.projects:
- ret += """<li><a href="#%s">%s</a></li>""" % (project.id, project.name)
-
- ret += "</ul>"
-
- for project in self.projects:
- ret += """<div id="%s">
- <p><strong>Description:</strong> %s</p>
- <br />
- <table class="translate">
- <tr>
- <th>Language</th>
- <th>Translated</th>
- <th>Untranslated</th>
- <th>Fuzzy</th>
- <th>Status</th>
- </tr>""" % (project.id, project.desc)
-
- total = 0
- if project.pot:
- total = project.pot.untranslated
-
- for t in sorted(project.translations):
- if total:
- percent = "%3.1f%%" % (t.translated * 100 / total)
- else:
- percent = "---.-%"
-
- ret += """\
- <tr>
- <td class="lang"><img src="/images/flags/%s.png" alt="%s" />%s</td>
- <td>%s</td>
- <td>%s</td>
- <td>%s</td>
- <td>%s</td>
- </tr>""" % \
- (t.code, t.code, t.lang, t.translated, t.untranslated, t.fuzzy, percent)
-
- ret += "</table>"
-
- if project.pot:
- ret += """\
- <p>
- <br />
- <strong>Template</strong> - %s strings
- </p>""" % project.pot.untranslated
-
- ret += "</div>"
-
- ret += "</div>"
- return ret
-
-page = web.Page()
-page.content = Content()
-page.sidebar = web.elements.DevelopmentSidebar()
-page.javascript = Javascript(1, 1)
-page.javascript.write("""
- <script type="text/javascript">
- $(function() {
- $("#tabs").tabs();
- });
- </script>
-""")
--- /dev/null
+[
+ { "name" : "IPFire 2.5 - Core 34",
+ "status" : "stable",
+ "online" : 1,
+ "files" : [
+ {
+ "type" : "alix",
+ "name" : "ipfire-2.5.1gb-ext2-scon.i586-full-core34.img.gz",
+ "sha1" : "7f1fbea61842ff89197aede66da29a5e436543c3"
+ },
+ {
+ "type" : "flash",
+ "name" : "ipfire-2.5.1gb-ext2.i586-full-core34.img.gz",
+ "sha1" : "26e60ee522b8a006f9c3e26e0077446d444cf27a"
+ },
+ {
+ "type" : "iso",
+ "name" : "ipfire-2.5.i586-full-core34.iso",
+ "sha1" : "91ad4fb774bf14b4eb2e13c26caf066438b281aa"
+ },
+ {
+ "type" : "torrent",
+ "name" : "ipfire-2.5.i586-full-core34.iso.torrent",
+ "hash" : "50DC8E935D63ACAC02E5A3C21477EE59D7F1A06D"
+ },
+ {
+ "type" : "usbfdd",
+ "name" : "ipfire-2.5-install-usb-fdd.i586-full-core34.img.gz",
+ "sha1" : "a038d5af7e6e052f5df0199c729316e19ce202d1"
+ },
+ {
+ "type" : "usbhdd",
+ "name" : "ipfire-2.5-install-usb-hdd.i586-full-core34.img.gz",
+ "sha1" : "5a53677b757fa5515ecb686ac4b22739e11da7c1"
+ },
+ {
+ "type" : "xen",
+ "name" : "ipfire-2.5.xen.i586-full-core34.tar.bz2",
+ "sha1" : "05f062b1c0499a0d949127f7d048dda959feb9ac"
+ }
+ ]
+ },
+
+ { "name" : "IPFire 2.5 - Core 33",
+ "status" : "stable",
+ "online" : 1,
+ "files" : [
+ {
+ "type" : "alix",
+ "name" : "ipfire-2.5.1gb-ext2-scon.i586-full-core33.img.gz",
+ "sha1" : "04e0634ce5e0445c77a8278e254ca7084f68e30a"
+ },
+ {
+ "type" : "flash",
+ "name" : "ipfire-2.5.1gb-ext2.i586-full-core33.img.gz",
+ "sha1" : "1e3a8b0594fe92bb237bfabe10a8a10d687773f2"
+ },
+ {
+ "type" : "iso",
+ "name" : "ipfire-2.5.i586-full-core33.iso",
+ "sha1" : "c60c7bbe625044e96790c4ee3a30eaffb89aa379"
+ },
+ {
+ "type" : "torrent",
+ "name" : "ipfire-2.5.i586-full-core33.iso.torrent",
+ "hash" : "D9992ED673EC9D92774452962F4445993ECA730E"
+ },
+ {
+ "type" : "usbfdd",
+ "name" : "ipfire-2.5-install-usb-fdd.i586-full-core33.img.gz",
+ "sha1" : "5e8888afb035881f07ef318fc75dda7a3ab16840"
+ },
+ {
+ "type" : "usbhdd",
+ "name" : "ipfire-2.5-install-usb-hdd.i586-full-core33.img.gz",
+ "sha1" : "6b1e702d5cf2f317ff52371ecd7e68828b56f262"
+ },
+ {
+ "type" : "xen",
+ "name" : "ipfire-2.5.xen.i586-full-core33.tar.bz2",
+ "sha1" : "04e0634ce5e0445c77a8278e254ca7084f68e30a"
+ }
+ ]
+ },
+
+ { "name" : "IPFire 3.0 alpha 1",
+ "status" : "development",
+ "online" : 1,
+ "files" : [
+ {
+ "type" : "iso",
+ "name" : "ipfire-3.0-alpha1.i686.iso",
+ "sha1" : "e5d6c236a8997de8f1718f1c44f5a9d8f7d90af6"
+ }
+ ]
+ },
+
+ { "name" : "IPFire 1.4.9 - FINAL",
+ "status" : "stable",
+ "online" : 1,
+ "files" : [
+ {
+ "type" : "iso",
+ "name" : "IPFire-1.4.9-FINAL.iso",
+ "sha1" : "ba40ca010f6c3069f110f6b7d99e3524bd81d367"
+ }
+ ]
+ }
+]
+++ /dev/null
-#!/usr/bin/python
-
-import cgi
-import simplejson as json
-
-from rpc_functions import *
-
-form = cgi.FieldStorage()
-method = form.getfirst("method")
-id = form.getfirst("id")
-
-params = None
-param_string = form.getfirst("params")
-if param_string:
- params = json.loads(param_string)
-
-methods = { "cluster_get_info" : cluster_get_info,
- "uriel_send_info" : uriel_send_info, }
-
-if method and methods.has_key(method):
- print json.dumps({ "version": "1.1",
- "id": id or "null",
- "result" : methods[method](params),
- "error" : "null", },
- sort_keys=True, indent=4)
+++ /dev/null
-#!/usr/bin/python
-
-import time
-
-import web.info
-
-info = web.info.Info()
-
-def cluster_get_info(params):
- import web.cluster
- cluster = web.cluster.Cluster(info["hosting"]["cluster"])
- return cluster.json
-
-def uriel_send_info(params):
- import web.urieldb
- db = web.urieldb.Urieldb()
-
- id = None
- items = {}
- for (item, value) in params.items():
- if item == "id":
- id = value
- if item not in web.urieldb.allowed_items:
- continue
- items[item] = value
-
- # We need an id
- if not id:
- return
-
- for item, value in items.items():
- db.set(id, item, value)
-
- # Save date of last modification
- db.set(id, "date", "%s" % int(time.time()))
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<rss version="2.0">
- <channel>
- <title>IPFire.org - News</title>
- <link>http://www.ipfire.org/</link>
- <description>IPFire News Feed</description>
- <language>%(lang)s</language>
- <copyright>IPFire-Team</copyright>
- <pubDate>Thu, 8 Nov 2007 00:00:00 +0200</pubDate>
- %(content)s
- </channel>
-</rss>
{
font-family: "Verdana", "Deja-Vu Sans", "Bitstream Vera Sans", sans-serif;
font-size: 0.9em;
- background: #880400; /* url(/images/bg.png) repeat;*/
+ background: #880400; /* url(../images/bg.png) repeat;*/
color: #585858;
}
line-height: 1.5em;
}
+p.right {
+ float: right;
+}
+
/* Header */
#header
{
width:100%;
height:102px;
-background: url('/images/bg-menu99.png') repeat-x;
+background: url('../images/bg-menu99.png') repeat-x;
}
#header_inner
#menu li
{
vertical-align: middle;
-background: #333 url('/images/btn-break.png') center;
+background: #333 url('../images/btn-break.png') center;
}
#menu li a
{
display: block;
padding: 10px 5px 0 8px;
height: 26px;
-background: #333 url('/images/btn-empty.png') repeat-x center;
+background: #333 url('../images/btn-empty.png') repeat-x center;
color: #ddd;
font-weight: bolder;
vertical-align: middle;
#menu li a.active
{
-background: #CA2F2F url('/images/btn-red2.png') repeat-x center;
+background: #CA2F2F url('../images/btn-red2.png') repeat-x center;
color: #ddd;
}
#menu li a:hover
{
-background: #333 url('/images/btn-red2.png') repeat-x center;
+background: #333 url('../images/btn-red2.png') repeat-x center;
color: #fff;
}
#main
{
-/* background: #fff url('images/n2.gif') 0px 1px repeat-x; */
+/* background: #fff url('../images/n2.gif') 0px 1px repeat-x; */
}
#main_inner p
#main_inner .post ul.post_info li.date
{
-background-image: url('images/n5.gif');
+background-image: url('../images/n5.gif');
}
#main_inner .post ul.post_info li.comments
{
-background-image: url('images/n6.gif');
+background-image: url('../images/n6.gif');
margin-left: 1.1em;
}
font-size: 0.9em;
}
#sh-tl {
- background: url(/images/sh-tl.png) no-repeat right bottom;
+ background: url("../images/sh-tl.png") no-repeat right bottom;
}
#sh-top {
- background: url(/images/sh-top.png) repeat-x bottom;
+ background: url("../images/sh-top.png") repeat-x bottom;
}
#sh-tr {
- background: url(/images/sh-tr.png) no-repeat left bottom;
+ background: url("../images/sh-tr.png") no-repeat left bottom;
}
#sh-lft {
- background: url(/images/sh-lft.png) repeat-y right;
+ background: url("../images/sh-lft.png") repeat-y right;
}
#sh-rgt {
- background: url(/images/sh-rgt.png) repeat-y left;
+ background: url("../images/sh-rgt.png") repeat-y left;
}
#sh-bl {
- background: url(/images/sh-bl.png) no-repeat right top;
+ background: url("../images/sh-bl.png") no-repeat right top;
}
#sh-btn {
- background: url(/images/sh-btn.png) repeat-x top;
+ background: url("../images/sh-btn.png") repeat-x top;
}
#sh-br {
- background: url(/images/sh-br.png) no-repeat left top;
+ background: url("../images/sh-br.png") no-repeat left top;
}
#no-sh {
background-color: #f5f5f5;
height: 26px;
color: #ddd;
text-align: center;
-background: url(/images/ft.png) left top;
+background: url("../images/ft.png") left top;
margin-top: 0em;
margin-bottom: 0em;
padding-top: 0.5em;
input.button
{
-background: #CA2F2F url('images/n3.gif') repeat-x;
+background: #CA2F2F url("../images/n3.gif") repeat-x;
color: #fff;
border: solid 1px #A94B4B;
font-weight: bold;
.thumbnail span{ /*CSS for enlarged image*/
position: absolute;
-background-color: lightyellow;
+background-color: #ffffe0; /*lightyellow;*/
padding: 5px;
left: -1000px;
border: 1px dashed gray;
.feed {
margin-left: 3px;
padding: 0 0 0 19px;
- background: url("/images/feed.png") no-repeat 0 50%;
+ background: url("../images/feed.png") no-repeat 0 50%;
}
/* LAYOUT - 3 COLUMNS */
/* Component containers */
.ui-widget-content {
border: 1px solid #999/*{borderColorContent}*/;
- background: #F5F5F5/*{bgColorContent}*/ 50%/*{bgContentXPos}*/ url(/images/ui-bg_flat_75_f5f5f5_40x100.png)/*{bgImgUrlDefault}*/50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/;
+ background: #F5F5F5/*{bgColorContent}*/ 50%/*{bgContentXPos}*/ url(../images/ui-bg_flat_75_f5f5f5_40x100.png)/*{bgImgUrlDefault}*/50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/;
color: #222222/*{fcContent}*/;
}
.ui-widget-content a {
}
.ui-widget-header {
border: 1px solid #aaaaaa/*{borderColorHeader}*/;
- background: #cccccc/*{bgColorHeader}*/ url(/images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/;
+ background: #cccccc/*{bgColorHeader}*/ url(/../images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/;
color: #222222/*{fcHeader}*/;
font-weight: bold;
}
/* Interaction states */
.ui-state-default, .ui-widget-content .ui-state-default {
border: 1px solid #d3d3d3/*{borderColorDefault}*/;
- background: #e6e6e6/*{bgColorDefault}*/ url(/images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/;
+ background: #e6e6e6/*{bgColorDefault}*/ url(../images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/;
font-weight: normal/*{fwDefault}*/;
color: #555555/*{fcDefault}*/;
outline: none;
}
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus {
border: 1px solid #999999/*{borderColorHover}*/;
- background: #dadada/*{bgColorHover}*/ url(/images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/;
+ background: #dadada/*{bgColorHover}*/ url(../images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/;
font-weight: normal/*{fwDefault}*/;
color: #212121/*{fcHover}*/;
outline: none;
/* IPFire Download Button */
.button {
- background: url(/images/buttons/download_core_96x320.png);
+ background: url(../images/buttons/download_core_96x320.png);
background-repeat: no-repeat;
background-position: right;
width: 700px;
/* CeBIT Button */
.cebit_button {
- background: url(/images/buttons/cebit_96x320.png);
+ background: url(../images/buttons/cebit_96x320.png);
background-repeat: no-repeat;
background-position: right;
width: 700px;
color:#333;
font-size: 20px !important;
text-shadow: #666 1px 2px 2px;
- padding: 51px 0px 0px 472px;
+ padding: 51px 0px 0px 465px;
+}
+
+/* Public Relations linklists */
+.pr_li {
+ padding: 0px 0px 0px 20px;
+ line-height: 1.2em;
+}
+
+div.bigdownload {
+ margin-top: 50px;
+ margin-left: 100px;
+ padding-top: 15px;
+ background: url(../images/download_button.png) no-repeat;
+ height: 84px;
+ width: 255px;
+ text-align: center;
+}
+
+div.bigdownload a {
+ color: white;
+ font-size: 1.3em;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+div.bigdownload a:hover {
+ text-decoration: underline;
+}
+
+table.download {
+ width: 660px;
+ margin-left: 75px;
+}
+
+table.download td.icon {
+ width: 50px;
+}
+
+table.download td.link {
+ width: 180px;
+}
+
+table.download-torrents {
+ margin-bottom: 25px;
+ margin-left: 50px;
+ margin-top: 25px;
+ width: 600px;
+}
+
+table.download-torrents tr {
+ height: 24px;
+}
+
+table.download-torrents td {
+ text-align: center;
+}
+
+table.download-torrents th.seeds, th.peers, td.seeds, td.peers {
+ text-align: right;
+}
+
+table.download-torrents th.peers,td.peers {
+ padding-left: 5px;
+}
+
+table.download-mirrors {
+ margin-bottom: 25px;
+ margin-left: 15px;
+ margin-top: 25px;
+ width: 700px;
+}
+
+table.download-mirrors tr {
+ height: 32px;
+}
+
+table.download-mirrors tr.legend {
+ text-align: right;
+}
+
+table.download-mirrors td {
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table.download-mirrors tr.unreachable, td.unreachable {
+ border: 1px solid #f55;
+ background-color: #f99;
+}
+
+table.download-mirrors tr.reachable, td.reachable {
+ border: 1px solid #5f5;
+ background-color: #9f9;
+}
+
+table.download-mirrors td.latency {
+ width: 70px;
+ text-align: right;
+}
+
+ul.sources li {
+ font-family: courier;
+ list-style-type: none;
}
--- /dev/null
+nodes = new Array();
+id = 0;
+busy = false;
+
+update = function() {
+ $.getJSON("/api/cluster_info", { id : id++ },
+ function(data) {
+ // If we are already busy then exit
+ if (busy == true) return;
+
+ var count = 0;
+
+ if (data.error != "null") return;
+
+ busy = true;
+
+ $.each(data.result.nodes, function(i, node) {
+ var nodeid = node.hostname.replace(/\./g, "");
+ count++;
+
+ nodes[nodeid] = true;
+
+ if ($("#" + nodeid).length) {
+ $("#" + nodeid + "_speed").html(node.speed);
+ } else {
+ row = "<tr id=\"" + nodeid + "\" class=\"node\">";
+ row += " <td id=\"" + nodeid + "_hostname\"></td>";
+ row += " <td id=\"" + nodeid + "_arch\">" + node.arch + "</td>";
+ row += " <td><span id=\"" + nodeid + "_loadbar\"></span></td>";
+ row += " <td><span id=\"" + nodeid + "_jobs\"></span></td>";
+ row += " <td id=\"" + nodeid + "_speed\">" + node.speed + "</td>";
+ row += "</tr>";
+ $("#nodes").append(row);
+ }
+ $("#" + nodeid + "_loadbar").progressBar(node.load, {showText: false});
+ $("#" + nodeid + "_jobs").progressBar(node.jobcount.split("/")[0], { max: node.jobcount.split("/")[1], textFormat: 'fraction'});
+ if (node.installing == true) {
+ $("#" + nodeid + "_hostname").html(node.hostname + " *");
+ } else {
+ $("#" + nodeid + "_hostname").html(node.hostname);
+ }
+ });
+
+ $("#loadbar").progressBar(data.result.cluster.load);
+ $("#jobbar").progressBar(data.result.cluster.jobcount.split("/")[0], { max: data.result.cluster.jobcount.split("/")[1], textFormat: 'fraction'});
+ for (var nodeid in nodes) {
+ if (nodes[nodeid] == false) {
+ $("#" + nodeid).remove();
+ nodes.pop(nodeid);
+ } else {
+ nodes[nodeid] = false;
+ }
+ }
+ $("#count").html(count);
+ busy = false;
+ });
+}
+
+$(document).ready(function(){
+ // Init loadbar
+ $("#loadbar").progressBar();
+
+ update();
+ setInterval("update()", 2000);
+})
* @license CC Attribution-No Derivative Works 2.5 Brazil - http://creativecommons.org/licenses/by-nd/2.5/br/deed.en_US
* @example Visit http://leandrovieira.com/projects/jquery/lightbox/ for more informations about this jQuery plugin
*/
-(function($){$.fn.lightBox=function(settings){settings=jQuery.extend({overlayBgColor:'#000',overlayOpacity:0.8,fixedNavigation:false,imageLoading:'/images/lightbox/lightbox-ico-loading.gif',imageBtnPrev:'/images/lightbox/lightbox-btn-prev.gif',imageBtnNext:'/images/lightbox/lightbox-btn-next.gif',imageBtnClose:'/images/lightbox/lightbox-btn-close.gif',imageBlank:'/images/lightbox/lightbox-blank.gif',containerBorderSize:10,containerResizeSpeed:400,txtImage:'Image',txtOf:'of',keyToClose:'c',keyToPrev:'p',keyToNext:'n',imageArray:[],activeImage:0},settings);var jQueryMatchedObj=this;function _initialize(){_start(this,jQueryMatchedObj);return false;}
+(function($){$.fn.lightBox=function(settings){settings=jQuery.extend({overlayBgColor:'#000',overlayOpacity:0.8,fixedNavigation:false,imageLoading:'/static/images/lightbox/lightbox-ico-loading.gif',imageBtnPrev:'/static/images/lightbox/lightbox-btn-prev.gif',imageBtnNext:'/static/images/lightbox/lightbox-btn-next.gif',imageBtnClose:'/static/images/lightbox/lightbox-btn-close.gif',imageBlank:'/static/images/lightbox/lightbox-blank.gif',containerBorderSize:10,containerResizeSpeed:400,txtImage:'Image',txtOf:'of',keyToClose:'c',keyToPrev:'p',keyToNext:'n',imageArray:[],activeImage:0},settings);var jQueryMatchedObj=this;function _initialize(){_start(this,jQueryMatchedObj);return false;}
function _start(objClicked,jQueryMatchedObj){$('embed, object, select').css({'visibility':'hidden'});_set_interface();settings.imageArray.length=0;settings.activeImage=0;if(jQueryMatchedObj.length==1){settings.imageArray.push(new Array(objClicked.getAttribute('href'),objClicked.getAttribute('title')));}else{for(var i=0;i<jQueryMatchedObj.length;i++){settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),jQueryMatchedObj[i].getAttribute('title')));}}
while(settings.imageArray[settings.activeImage][0]!=objClicked.getAttribute('href')){settings.activeImage++;}
_set_image_to_view();}
-(function($){$.extend({progressBar:new function(){this.defaults={steps:20,step_duration:20,max:100,showText:true,textFormat:'percentage',width:120,height:12,callback:null,boxImage:'/images/progressbar.gif',barImage:{0:'/images/progressbg_green.gif',30:'/images/progressbg_orange.gif',70:'/images/progressbg_red.gif'},running_value:0,value:0,image:null};this.construct=function(arg1,arg2){var argvalue=null;var argconfig=null;if(arg1!=null){if(!isNaN(arg1)){argvalue=arg1;if(arg2!=null){argconfig=arg2;}}else{argconfig=arg1;}}
+(function($){$.extend({progressBar:new function(){this.defaults={steps:20,step_duration:20,max:100,showText:true,textFormat:'percentage',width:120,height:12,callback:null,boxImage:'/static/images/progressbar.gif',barImage:{0:'/static/images/progressbg_green.gif',30:'/static/images/progressbg_orange.gif',70:'/static/images/progressbg_red.gif'},running_value:0,value:0,image:null};this.construct=function(arg1,arg2){var argvalue=null;var argconfig=null;if(arg1!=null){if(!isNaN(arg1)){argvalue=arg1;if(arg2!=null){argconfig=arg2;}}else{argconfig=arg1;}}
return this.each(function(child){var pb=this;var config=this.config;if(argvalue!=null&&this.bar!=null&&this.config!=null){this.config.value=argvalue
if(argconfig!=null)
pb.config=$.extend(this.config,argconfig);config=pb.config;}else{var $this=$(this);var config=$.extend({},$.progressBar.defaults,argconfig);config.id=$this.attr('id')?$this.attr('id'):Math.ceil(Math.random()*100000);if(argvalue==null)
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
- <title>%(title)s</title>
+ <title>{% block title %}{{ title }}{% end block %}</title>
<meta name="keywords" content="Linux, Firewall, IPFire, Security" />
<meta name="description" content="" />
<meta name="verify-v1" content="2LEf3W8naILGWVy2dhedSVEHPXTpp2xFNVsHXZMH1JI=" />
- <link rel="stylesheet" type="text/css" href="/include/style.css" />
- <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.ipfire.org/%(lang)s/news.rss" />
- <!--[if lt IE 7]>
- <link rel="stylesheet" type="text/css" href="/include/ie6.css" />
- <script src="/include/correctpng.js" type="text/javascript"></script>
- <![endif]-->
- %(javascript)s
+ <link rel="stylesheet" type="text/css" href="{{ static_url("css/style.css") }}" />
+ <script type="text/javascript" src="{{ static_url("js/jquery.js") }}"></script>
+ <script type="text/javascript" src="{{ static_url("js/jquery-ui.js") }}"></script>
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.ipfire.org/{{ lang }}/news.rss" />
+ <!--[if lt IE 7]>
+ <link rel="stylesheet" type="text/css" href="{{ static_url("css/ie6.css") }}" />
+ <script src="{{ static_url("js/correctpng.js") }}" type="text/javascript"></script>
+ <![endif]-->
</head>
<body>
<div id="header">
<div id="header_inner" class="fixed">
<div id="logo">
- <a href="/" accesskey="h" title="[ALT+H]"><img src="/images/tux_menu_99x100.png" width="100px" height="99px" class="symbol" alt="IPFire" /></a>
+ <a href="{{ link("") }}">
+ <img src="{{ static_url("images/tux_menu_99x100.png") }}" class="symbol" alt="IPFire" />
+ </a>
</div>
<div id="line1">
- %(menu)s
+ {% block menu %}
+ {{ modules.Menu() }}
+ {% end block %}
<div id="lang">
- %(languages)s
+ {% block languages %}
+ {% for lng in langs %}
+ <a href="{{ lang_link(lng) }}"><img src="{{ static_url("images/%s.gif" % lng) }}" alt="{{ lng }}" /></a>
+ {% end %}
+ {% end block %}
</div>
</div>
<div id="line2">
- <h1>%(server)s</h1>
+ <h1>{{ server }}</h1>
</div>
<div id="line3">
- <h2>%(slogan)s</h2>
+ <h2>{{ _("Security gone easy!") }}</h2>
</div>
</div>
<td id="no-sh">
<div id="primaryContent_2columns">
<div id="columnA_2columns">
- %(content)s
+ {% block content %}
+ {% end block %}
<br class="clear" />
</div>
</div>
<div id="secondaryContent_2columns">
<div id="columnC_2columns">
- %(sidebar)s
+ {% block sidebar %}
+ {{ modules.SidebarBanner(banner) }}
+ {% end block %}
<br class="clear" />
</div>
</div>
<tr>
<td id="sh-lft"></td>
<td id="footer" class="fixed2">
- Copyright © %(year)s IPFire.org. All rights reserved. <a href="/%(lang)s/imprint">Imprint</a>
+ Copyright © {{ year }} IPFire.org. All rights reserved. <a href="{{ link("imprint") }}">{{ _("imprint") }}</a>
</td>
<td id="sh-rgt"></td>
</tr>
</table>
</div>
</div>
+ {% block javascript %}{% end block %}
</body>
</html>
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Builds") }}{% end block %}
+
+{% block content %}
+ <h3>{{ _("Nightly builds") }}</h3>
+
+ <table id="builds">
+ <tbody>
+ {% if builds["<12h"] %}
+ <tr class="headline">
+ <td colspan="3">
+ {{ _("Less than 12 hours ago") }}
+ </td>
+ </tr>
+ {% for build in builds["<12h"] %}
+ {{ modules.Build(build) }}
+ {% end %}
+ {% end %}
+
+ {% if builds[">12h"] %}
+ <tr class="headline">
+ <td colspan="3">
+ {{ _("More than 12 hours ago") }}
+ </td>
+ </tr>
+ {% for build in builds[">12h"] %}
+ {{ modules.Build(build) }}
+ {% end %}
+ {% end %}
+
+ {% if builds[">24h"] %}
+ <tr class="headline">
+ <td colspan="3">
+ {{ _("More than a day ago") }}
+ </td>
+ </tr>
+ {% for build in builds[">24h"] %}
+ {{ modules.Build(build) }}
+ {% end %}
+ {% end %}
+ </tbody>
+ </table>
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+ <div class="post">
+ <h3>{{ _("Download IPFire") }}</h3>
+ <img src="{{ static_url("images/page_icons/download-all.png") }}" class="floatTR" border="0" alt="{{ _("Download IPFire") }}" />
+ <p>
+ {{ _("These are the ancient downloads of IPFire. They are just saved for historical reasons and should not be used in a productive environment.") }}
+ </p>
+
+ <p>
+ <a href="{{ link("downloads") }}">{{ _("Get back to latest stable downloads.") }}</a>
+ </p>
+
+ <br class="clear" />
+ </div>
+
+ {% for release in releases.stable %}
+ {% if not release == releases.latest %}
+ {{ modules.ReleaseItem(release) }}
+ {% end %}
+ {% end %}
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+ <div class="post">
+ <h3>{{ _("Development Downloads") }}</h3>
+ <img src="{{ static_url("images/page_icons/download-developmemt.png") }}"
+ class="floatTR" border="0" alt="{{ _("Development Downloads") }}" />
+
+ {% if lang == "de" %}
+ <p>
+ In regelmäßigen Abständen wird aus dem aktuellen Quellcode der
+ Entwicklungsversion ein installationsfähiges Image als
+ technologische Vorschau erstellt.<br />
+ Diese Versionen dienen dazu einen stabilen Stand einer größeren
+ Menge an Testern zukommen zu lassen und sind <strong>nicht</strong>
+ für den Produktiveinsatz bestimmt.
+ </p>
+ {% else %}
+ <p>
+ The developers do create a snapshort version from the current
+ development sources to get this distributed to a higher number
+ of testers.<br />
+ These versions are <strong>not</strong> intended to be used in a
+ productive environment.
+ {% end %}
+
+ <p>
+ <a href="{{ link("downloads") }}">{{ _("Get back to latest stable downloads.") }}</a>
+ </p>
+ </div>
+
+ {% for release in releases.development %}
+ {{ modules.ReleaseItem(release) }}
+ {% end %}
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+ <div class="post">
+ <a name="latest"></a>
+ <h3>{{ _("IPFire Mirrors") }}</h3>
+ <img src="{{ static_url("images/page_icons/download-mirrors.png") }}" class="floatTR" border="0" alt="{{ _("IPFire Torrent Tracker") }}" />
+
+ {% if lang == "de" %}
+ <p>
+ Diese Seite zeigt eine Liste der Mirror-Server des IPFire-Projektes.
+ </p>
+
+ <p>
+ Bei einem Download wird einer der Server zufällig aus der Liste
+ gewählt und der User umgeleitet.
+ </p>
+
+ <ul>
+ <li>
+ <a href="http://wiki.ipfire.org/{{ lang }}/project/web"
+ target="_blank">Wie stelle ich selbst einen Mirror-Server bereit?</a>
+ </li>
+ </ul>
+ {% else %}
+ <p>
+ This page is an overview about our mirror servers.
+ </p>
+
+ <p>
+ When a user downloads a file, one of the servers is arbitrarily
+ choosen und the user gets reditected.
+ </p>
+
+ <ul>
+ <li>
+ <a href="http://wiki.ipfire.org/{{ lang }}/project/web"
+ target="_blank">How do I contribute a mirror server?</a>
+ </li>
+ </ul>
+ {% end %}
+ <br class="clear" />
+
+ <table class="download-mirrors">
+ <tr>
+ <th>{{ _("Owner (Hostname)") }}</th>
+ <th>{{ _("Location") }}</th>
+ <th>{{ _("Latency") }}</th>
+ </tr>
+ {% for mirror in mirrors.all %}
+ <tr class="{% if not mirror.reachable %}un{% end %}reachable">
+ <td>{{ mirror.name }} ({{ mirror.hostname }})</td>
+ <td>
+ <img src="{{ static_url("images/flags/%s.png" % mirror.location["country_code"]) }}"
+ align="absmiddle" alt="{{ mirror.location["country_code"] }}" />
+ {{ mirror.location["country"] }}, {{ mirror.location["city"] }}
+ </td>
+ <td class="latency">{{ mirror.latency }} ms</td>
+ </tr>
+ {% end %}
+ <tr class="legend">
+ <td colspan="3"> </td>
+ </tr>
+ <tr class="legend">
+ <td><strong>{{ _("Legend") }}:</strong></td>
+ <td colspan="2" class="reachable">{{ _("Server is reachable") }}</td>
+ </tr>
+ <tr class="legend">
+ <td> </td>
+ <td colspan="2" class="unreachable">{{ _("Server is unreachable") }}</td>
+ </tr>
+ </table>
+
+ <br class="clear" />
+ </div>
+
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+ <div class="post">
+ <a name="latest"></a>
+ <h3>{{ _("IPFire Torrent Tracker") }}</h3>
+
+ <img src="{{ static_url("images/page_icons/download-torrents.png") }}"
+ class="floatTR" border="0" alt="{{ _("IPFire Torrent Tracker") }}" />
+
+ {% if lang == "de" %}
+ <p>
+ Auf dieser Seite findet man eine Liste fast aller Dateien, die
+ über den IPFire-Torrent-Tracker verteilt werden.
+ <p>
+ <p>
+ Das Torrentnetz ist ein Netzwerk, welches Dateien durch verteilte
+ Downloads schnell verbreitet. IPFire nutzt dieses System um
+ Downloads der Distributionsimages bereitzustellen.
+ </p>
+ <p>
+ Mehr Informationen zu Torrent-Netzwerken gibt es in der
+ <a href="http://de.wikipedia.org/wiki/BitTorrent"
+ target="_blank">Wikipedia</a>.
+ </p>
+ {% else %}
+ <p>
+ This page displays a list of files that are tracked by the
+ IPFire torrent tracker.
+ <p>
+ <p>
+ The bittorrent protocol transfers large files by a distributed
+ technology. IPFire uses this system to spread the distribution's
+ files.
+ </p>
+ <p>
+ Get more information on the bittorrent protocol on
+ <a href="http://en.wikipedia.org/wiki/BitTorrent_(protocol)"
+ target="_blank">Wikipedia</a>.
+ </p>
+ {% end %}
+
+ <br class="clear" />
+
+
+ <table class="download-torrents">
+ <tr>
+ <th>{{ _("Release") }}</th>
+ <th>{{ _("File") }}</th>
+ <th class="seeds">S</th>
+ <th class="peers">P</th>
+ <th> </th>
+ </tr>
+ {% for release in releases %}
+ <tr>
+ <td>{{ release.name }}</td>
+ <td>{{ release.torrent.file[:-8] }}</td>
+ <td class="seeds">{{ hashes[release.torrent.hash]["seeds"] }}</td>
+ <td class="peers">{{ hashes[release.torrent.hash]["peers"] }}</td>
+ <td class="download">
+ <a href="{{ release.torrent.url }}">{{ _("Download file") }}</a>
+ </td>
+ </tr>
+ {% end %}
+ </table>
+
+ <p class="right">
+ {{ _("Got that information from <em>%s</em> within %.2f second(s).") % (tracker, request_time) }}
+ </p>
+
+ <br class="clear" />
+ </div>
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Downloads") }}{% end block %}
+
+{% block content %}
+ <div class="post">
+ <a name="latest"></a>
+ <h3>{{ _("Download IPFire") }}</h3>
+
+ <img src="{{ static_url("images/box_ipfire.png") }}" alt="{{ _("CD-Box") }}" class="floatTR" />
+
+ {% if lang == "de" %}
+ <p>
+ Auf dieser Seite können Sie <strong>kostenlos</strong> die neueste
+ Version von IPFire herunterladen. Ältere Versionen oder
+ andere Downloadoptionen finden Sie weiter unten auf der Seite.
+ </p>
+
+ <p>
+ IPFire ist innerhalb von 15 bis 20 Minuten eingerichtet.
+ Eine <a href="http://wiki.ipfire.org/{{ lang }}/installation/start"
+ target="_blank">Installationsanleitung</a>
+ ist in unserem Wiki zu finden.
+ </p>
+
+ <p>
+ Sollte Ihnen diese Software gefallen, würden sich die Betreiber
+ über ein kleines Dankeschön freuen.
+ </p>
+ {% else %}
+ <p>
+ On this page one can download the latest version of IPFire
+ <strong>for free</strong>. Older versions and other downloads
+ can be retrieved on the linked pages below.
+ </p>
+
+ <p>
+ IPFire can be installed within 15 to 20 minutes. An
+ <a href="http://wiki.ipfire.org/{{ lang }}/installation/start"
+ target="_blank">installation guide</a> can be found on our wiki.
+ </p>
+
+ <p>
+ If you like this piece of software, developers appreciate your
+ donations.
+ </p>
+ {% end %}
+
+ <div class="bigdownload">
+ <a href="{{ release.iso.url }}">
+ {{ _("Begin download") }}<br />
+ {{ release.name }}
+ </a>
+ </div>
+
+ <table class="download">
+ {% for download in release.downloads %}
+ <tr class="{{ download.type }}">
+ <td class="icon">
+ <img src="{{ static_url("images/download_type_%s.png" % download.type) }}"
+ alt="{{ download.type }}" />
+ </td>
+ <td class="link">
+ <a href="{{ download.url }}">{{ _(download.desc) }}</a>
+ </td>
+ <td>
+ {{ _(download.rem) }}
+ </td>
+ </tr>
+ {% end %}
+ </table>
+
+ <br class="clear" />
+ </div>
+
+ <div class="post">
+ <a name="other"></a>
+ <h3>{{ _("Other download options") }}</h3>
+ <div class=pr_li>
+ <ul>
+ <li><a href="{{ link("downloads/all") }}">{{ _("See older downloads...") }}</a></li>
+ <li><a href="{{ link("downloads/development") }}">{{ _("See development releases...") }}</a></li>
+ <li><a href="{{ link("downloads/torrents") }}">{{ _("See all torrents...") }}</a></li>
+ <li><a href="{{ link("downloads/mirrors") }}">{{ _("See a list of mirrors...") }}</a></li>
+ </ul>
+ </div>
+ <br class="clear" />
+ </div>
+{% end block %}
--- /dev/null
+{% extends "error.html" %}
--- /dev/null
+{% extends "error.html" %}
+
+{% block explanation %}
+ <br class="clear" />
+
+ <h4>{{ _("Detailed information") }}</h4>
+ <p>
+ {% if lang == "de" %}
+ Bei der Verarbeitung der Anfrage kam es zu einem internen Problem
+ des Webservers.<br />Sollten nähere Informationen verfügbar sein, so
+ sind diese untenstehend angehangen.
+ {% else %}
+ While processing the request, there was an internal problem
+ of the web server. <br /> If there are more information available,
+ they would be appended below.
+ {% end %}
+ </p>
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Error") }} {{ code }}{% end block %}
+
+{% block content %}
+<div class=post>
+ <h3>{{ code }} - {{ message }}</h3>
+ <img class="floatTL" src="{{ static_url("images/error/%s.png" % code) }}"
+ alt="{{ _("Error") }} {{ code }}" />
+ <p>
+ {% if lang == "de" %}
+ Leider ist ein unerwarteter Fehler beim Laden der Seite aufgetreten.
+ <br /><br />
+ Das ist erstmal kein Grund zur Panik.
+ <br /><br />
+ Sollte dies das erstmalige Auftreten des Fehlers sein, so bitten wir
+ einige Zeit abzuwarten. Sollte der Fehler jedoch an dieser Stelle
+ regelmäßig auftreten, so würden sich die Webmaster über eine kleine
+ Benachrichtigung freuen.
+ {% else %}
+ Unfortunately, an unexpected error has occurred during page load.
+ <br /><br />
+ At first this is no reason to panic.
+ <br /><br />
+ If this is the first occurrence of the error, please wait a little bit
+ and try again. If the error occurres anyway the webmaster would be happy
+ to get a notification about this.
+ {% end %}
+ </p>
+</div>
+<div class=post>
+ {% block explanation %}{% end block %}
+</div>
+ {% if exception %}
+ <div class=post>
+ <p>
+ <pre>{{ exception }}</pre>
+ </p>
+ </div>
+ {% end %}
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Home") }}{% end block %}
+
+{% block content %}
+ <div class=post>
+ <h3>{{ _("More security for your network") }}</h3>
+ <p>
+ {% if lang == "de" %}
+ Das <strong>IPFire</strong>-System ist eine Linux-Distribution, mit der Zielsetzung ein einfach zu
+ installierendes Grundsystem zu bieten und dabei ein <strong>hohes Sicherheitsniveau</strong> zu gewährleisten.
+ <strong>IPFire</strong> ist komplett über sein intuitiv zu bedienendes Webinterface zu konfigurieren
+ und bietet sowohl <strong>Anfängern</strong>, als auch erfahrenen <strong>Administratoren</strong> eine Fülle von
+ Einstellungsmöglichkeiten. Einen <strong>Schwerpunkt</strong> bei der Weiterentwicklung legen die erfahrenen Entwickler
+ auf regelmäßige System- und vor allem <strong>Sicherheitsupdates</strong>.<br /><br />
+ Durch den integrierten Paketmanager <strong>Pakfire</strong> lässt sich der <strong>IPFire</strong> mit diversen
+ <a href="http://wiki.ipfire.org/de/addons/start" target="_blank">Addons</a>,
+ zu einem Server-System erweitern.
+ {% else %}
+ <strong>IPFire</strong> is a linux-distribution that focusses on easy setup, good handling and a
+ <strong>high niveau of security</strong>.<br /> It is operable via an intuitive webinterface, which offers a
+ lot of playground for <strong>beginners</strong> and even experienced <strong>administrators</strong>.
+ <strong>IPFire</strong> is maintained by experienced developers, who are really concerned about security and regulary
+ updates to <strong>keep it secure</strong>.<br /><br />
+ <strong>IPFire</strong> ships with a custom built paket-manager called <strong>Pakfire</strong>, so the system can be
+ expanded with various <a href="http://wiki.ipfire.org/en/addons/start" target="_blank">addons</a>.
+ {% end %}
+ </p>
+ <div class="cebit_button">
+ <div class="cebit_button_text">
+ <a href="cebit">{{ _("CeBIT-Donation") }}</a>
+ </div>
+ </div>
+ <!--
+ <div class="button">
+ <div class="button_text">
+ <a href="download">Download IPFire 2.5</a>
+ </div>
+ </div>
+ -->
+ <img src="{{ static_url("images/Network-1.png") }}") }}" alt="IPFire Network" />
+ </div>
+
+ <div class=post>
+ <h3>{{ _("News") }}</h3>
+
+ {% for item in news.get(2) %}
+ {{ modules.NewsItem(item) }}
+ {% end %}
+ </div>
+ <p class="right">
+ <a href="{{ link("news") }}">{{ _("Previous posts >>") }}</a>
+ </p>
+{% end block %}
+
+{% block sidebar %}
+ {{ modules.SidebarRelease() }}
+
+ <h4><span>Internet Relay</span> Chat</h4>
+ <p>
+ Server: irc.freenode.net<br />
+ Channel: #ipfire<br />
+ <a href="http://webchat.freenode.net/?channels=ipfire" target="_blank">Web-Chat</a>
+ </p>
+
+ {{ modules.SidebarBanner(banner) }}
+
+ <h4><span>RSS</span> feed</h4>
+ <p>
+ {% if lang == "de" %}
+ <a class="feed" href="news.rss">IPFire - News</a><br />
+ {% else %}
+ <a class="feed" href="news.rss">IPFire - News</a><br />
+ {% end %}
+ </p>
+
+{% end block %}
--- /dev/null
+<tr>
+ <td>
+ <img src="{{ static_url("images/icons/ipfire.png") }}" alt="IPFire" />
+ </td>
+ <td>
+ <br />
+ <strong>{{ build.release }}</strong> ({{ build.arch }})<br />
+ {{ build.date }}
+ </td>
+ <td>
+ <br />
+ <a href="#">{{ build.iso }}</a> | {{ build.size }}<br />
+ {{ build.pxe }}
+ </td>
+</tr>
--- /dev/null
+<li>
+ <a href="{{ item.uri }}"{% if item.active %} class="active"{% end %}>{{ item.name }}</a>
+</li>
--- /dev/null
+<div id="menu">
+ <ul>
+ {% for item in menuitems %}
+ {{ modules.MenuItem(item) }}
+ {% end %}
+ </ul>
+</div>
--- /dev/null
+<div class="post">
+ <a name="{{ item.subject }}"></a>
+ <h3>{{ item.subject }}</h3>
+ <div class="post_info">{{ item.date }} - {{ _("by") }} {{ item.author }}</div>
+ {{ item.content }}
+</div>
--- /dev/null
+<div class="post">
+ <h3>{{ item.name }}</h3>
+ <p>
+ {{ _("Here you will find the downloads for the version") }} {{ item.name }}:
+ </p>
+
+ <div align="right">
+ {% for download in item.downloads %}
+ <a class="{{ download.type }}" href="{{ download.url }}">{{ _(download.desc) }}</a><br />
+ {% end %}
+ </div>
+
+ <br class="clear" />
+</div>
--- /dev/null
+<h4>{{ item.title }}</h4>
+
+<a href="{{ item.link }}" {% if item.link.startswith("http://") %}target="_blank" {% end %}>
+ <img src="{{ static_url(item.uri) }}" border="0" alt="{{ _("Banner") }}" />
+</a>
--- /dev/null
+<h4>{% block heading %}{{ item.heading }}{% end block %}</h4>
+{% block body %}{{ item.body }}{% end block %}
--- /dev/null
+{% extends "sidebar-item.html" %}
+
+{% block heading %}{{ _("release information") }}{% end block %}
+
+{% block body %}
+ <p>
+ <img src="{{ static_url("images/ipfire_download.png") }}" alt="Tux Logo" />
+ </p>
+
+ <p>
+ <strong>{{ _("Current version") }}</strong>:
+ <br />
+ <a href="{{ link("downloads") }}">{{ releases.latest.name }}</a>
+ </p>
+
+ {% if releases.latest_devel %}
+ <p>
+ <strong>{{ _("Current unstable") }}</strong>:
+ <br />
+ <a href="{{ link("downloads/development") }}">{{ releases.latest_devel.name }}</a>
+ </p>
+ {% end %}
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block content %}
+ {% for item in news.get() %}
+ {{ modules.NewsItem(item) }}
+ {% end %}
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Sources") }}{% end block %}
+
+{% block content %}
+ <h3>{{ _("Source Code") }}</h3>
+
+ <p>
+ {{ _("There are %s source files on the server.") % len(files) }}
+ </p>
+
+ <br class="clear" />
+
+ <ul class="sources">
+ {% for file in files %}
+ <li>
+ {{ file["hash"] }} |
+ <a href="/{{ file["dir"] }}/{{ file["name"] }}">{{ file["name"] }}</a>
+ ({{ file["size"] }})
+ </li>
+ {% end %}
+ </ul>
+{% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}CeBIT-Special{% end block %}
+
+{% block content %}
+
+ <div class=post>
+ {% if lang == "de" %}
+ <h3>IPFire auf der CeBIT 2010</h3>
+ <img src="{{ static_url("images/cebit-177px_schatten.png") }}" class="floatTR" border="0" alt="CeBIT" />
+ <p>
+ Vom <em>2. bis 6. März 2010</em> findet die <strong>CeBIT</strong> in Hannover statt.
+ Das Besondere in diesem Jahr: <strong>IPFire</strong> wird mit einem
+ kleinen Stand in der <strong>Open Source Project Lounge</strong> auf der Messe vertreten sein.
+ </p>
+ <p>
+ Zuallererst gebührt unser Dank der
+ <a href="http://www.linuxnewmedia.de/Produkte/Events" target="_blank">Linux New Media AG</a>
+ und der <a href="http://www.cebit.de/opensource_d" target="_blank">Messegesellschaft</a>,
+ welche für ausgewählte OpenSource-Projekte einige kostenlose Stände zur Verfügung stellen.
+ Die <strong>CeBIT</strong> die weltgrößte Computer- und Telekommunikationsmesse,
+ und diese Präsentationsmöglichkeit ist natürlich eine riesige Chance, das Projekt bekannter
+ zu machen, mehr Nutzer und Entwickler zu erreichen, bzw. Kontakte zu knüpfen und Allianzen
+ zu schmieden.
+ </p>
+ <p>
+ Ebenfalls erhaltet ihr die einmalige Chance, die Entwickler einmal persönlich kennen zu lernen,
+ Ideen auszutauschen, und und und...
+ </p>
+ {% else %}
+ <h3>IPFire on CeBIT 2010</h3>
+ <img src="{{ static_url("images/cebit-177px_schatten.png") }}"class="floatTR" alt="CeBIT" />
+ <p>
+ <strong>CeBIT</strong> 2010 will be here soon, beginning March 2nd and lasting until
+ March 6th in Hannover, Germany. This year will prove to be a special
+ one, as <strong>IPFire</strong> will be represented by its very own booth in
+ the <strong>Open Source Project Lounge</strong>.
+ </p>
+ <p>
+ First of all, our very special thanks go out to
+ <a href="http://www.linuxnewmedia.de/Produkte/Events" target="_blank">Linux New Media AG</a> and
+ <a href="http://www.cebit.de/opensource_d" target="_blank">Messegesellschaft</a>,
+ who offer free booths to selected Open Source
+ projects. <strong>CeBIT</strong> (a German acronym for the Center for Office and
+ Information Technology) is the biggest computer and telecommunications
+ exhibition in the world. This an excellent chance for IPFire to gain
+ recognition, get in touch with users and developers, and possibly find
+ sponsors and forge alliances.
+ </p>
+ <p>
+ And, it is also a chance for all of you to meet the members of the
+ <strong>IPFire</strong> community in person.
+ </p>
+ {% end %}
+ </div>
+
+
+ <div class=post>
+ {% if lang == "de" %}
+ <h3>Spendenaufruf</h3>
+ <img src="{{ static_url("images/paypal-folder.png") }}" class="floatTL" alt="Paypal" />
+ <p>
+ Dieses Projekt wird von Freiwilligen in ihrer Freizeit betrieben und betreut, was auch
+ für den Stand zutrifft. Man glaubt es kaum, aber selbst wenn man einen kostenlosen
+ Stand zur Verfügung gestellt bekommt, entstehen hohe Kosten für Flyer, CDs, Poster und
+ sonstige Merchandise-Artikel.
+ </p>
+ <p>
+ Wir möchten jedoch <strong>IPFire</strong> so professionell wie möglich präsentieren, daher ergeht
+ an Sie Alle ein <strong>Spenden- und Mitmachaufruf</strong>.<br />
+ Wir möchten diese einmalige Chance nutzen und <strong>IPFire</strong> noch bekannter machen.
+ </p>
+ <p>
+ Spenden müssen nicht unbedingt finanzieller Natur sein. Es wird auch folgendes benötigt:
+ </p>
+
+ <p>
+ <ul>
+ <li>Poster</li>
+ <li>Flyer</li>
+ <li>CD-ROMs (bedruckt) in großer Auflage</li>
+ <li>Textilien mit Aufdruck</li>
+ </ul>
+ </p>
+ <p>
+ Wegen des einfachen Ablaufs der Spende bevorzugen wir <strong>PayPal</strong>.
+ Auf <a href="mailto:michael.tremer@ipfire.org" class="mail JSnocheck" title="michael.tremer@ipfire.org">Anfrage</a>
+ kann eine Ãœberweisung auch per Kontonummer erfolgen.
+ </p>
+ <div align="center">
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+ <input type="hidden" name="cmd" value="_s-xclick">
+ <input type="hidden" name="hosted_button_id" value="10718640">
+ <input type="image" src="https://www.paypal.com/de_DE/DE/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
+ <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+ </form>
+ </div>
+ {% else %}
+ <h3>Your Donations are Needed!</h3>
+ <p>
+ This project is driven and maintained by volunteers in their free time.
+ The same goes to the booth. Even though it is being donated there are
+ still many costs associated with running a booth, such as flyers, CDs,
+ posters and other merchandise.
+ </p>
+ <p>
+ As we strive to represent <strong>IPFire</strong> as professionally,
+ we are asking for some extra help to take advantage of this opportunity.
+ All we ask is a small donation, as every little bit helps. This is a unique
+ opportunity to gain international recognition for the project, so your
+ money will be well spent.
+ </p>
+ <p>
+ Materials we will be purchasing:
+ </p>
+ <p>
+ <ul>
+ <li>Posters</li>
+ <li>Flyers</li>
+ <li>Discs (pressed)</li>
+ <li>T-Shirts, etc.</li>
+ </ul>
+ </p>
+ <p>
+ Our favorite way for a donation is <strong>PayPal</strong> because
+ it is fast and easy. If you prefer a bank donation, please send
+ us a short <a href="mailto:michael.tremer@ipfire.org" class="mail JSnocheck" title="michael.tremer@ipfire.org">request</a>
+ for our bank account number.
+ </p>
+ <div align="center">
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+ <input type="hidden" name="cmd" value="_s-xclick">
+ <input type="hidden" name="hosted_button_id" value="10718640">
+ <input type="image" src="https://www.paypal.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
+ <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+ </form>
+ </div>
+ {% end %}
+ </div>
+
+
+ <div class=post>
+ {% if lang == "de" %}
+ <h3>Sponsoren</h3>
+ {% else %}
+ <h3>Sponsors</h3>
+ {% end %}
+ <a href="http://www.linuxnewmedia.de/" target="_blank" border"0"><img src="{{ static_url("images/linux_new_media_ag.jpg") }} alt="Linux New Media AG" /></a>
+ <a href="http://www.aktinet.de/" target="_blank" border="0"><img src="{{ static_url("images/aktinet_logo.jpg") }} alt="Aktinet IT-Services" /></a>
+ </div>
+
+
+{% end block %}
+
+{% block sidebar %}
+ <h4><span>Ce</span>BIT</h4>
+ {% if lang == "de" %}
+ <ul class="links">
+ <li class="first"><a href="#IPFire auf der CeBIT 2010">CeBIT 2010</a></li>
+ <li><a href="#Spendenaufruf">Spenden!</a></li>
+ <li><a href="#Sponsoren">Sponsoren</a></li>
+ </ul>
+ {% else %}
+ <ul class="links">
+ <li class="first"><a href="#IPFire on CeBIT 2010:">CeBIT 2010</a></li>
+ <li><a href="#Your Donations are Needed!">Donation!</a></li>
+ <li><a href="#Sponsors">Sponsors</a></li>
+ </ul>
+ {% end %}
+
+{{ modules.SidebarBanner(banner) }}
+
+{% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Cluster") }}{% end block %}
+
+{% block content %}
+ <h3>{{ _("Icecream Cluster Monitoring") }}</h3>
+
+ <p>{{ _("Cluster's CPU load") }}:
+ <span id="loadbar"></span>
+ - {{ _("Job load") }}:
+ <span id="jobbar"></span>
+ </p>
+
+ <table id="nodes">
+ <thead>
+ <tr>
+ <th class="hostname">{{ _("Name") }}</th>
+ <th class="arch">{{ _("Arch") }}</th>
+ <th class="load">{{ _("CPU-Load") }}</th>
+ <th class="jobs">{{ _("Jobs") }}</th>
+ <th class="speed">{{ _("Speed") }}</th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+
+ <p class="right"> <br />{{ _("Number of nodes") }}: <span id="count">-</span></p>
+
+{% end block %}
+
+{% block javascript %}
+ <script type="text/javascript" src="{{ static_url("js/jquery.progressbar.js") }}"></script>
+ <script type="text/javascript" src="{{ static_url("js/cluster.js") }}"></script>
+{% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Development") }}{% end block %}
+
+{% block content %}
+
+
+ <div class=post>
+ <h3>{{ _("Development") }}</h3>
+ <img src="{{ static_url("images/page_icons/development.png") }}" class="floatTR" border="0" alt="{{ _("Development") }}" />
+ <p>
+ {% if lang == "de" %}
+ Willkommen im Entwicklungsbereich des IPFire-Projekts.<br />
+ Hier gibt es Zugriff auf alle Ressourcen für die Entwicklung.<br />
+ {% else %}
+ Welcome to the development area of the ipfire project.<br />
+ These are the development ressources.
+ {% end %}
+ </p>
+ </div>
+ <br class="clear" />
+
+ <div class=post>
+ <h3>{{ _("git") }}</h3>
+ <img src=" http://git.ipfire.org/git-logo.png" class="floatTL" alt="{{ _("git") }}" />
+ <p>
+ {% if lang == "de" %}
+ Das Quellcode-Repository wird durch
+ <a href="http://git.or.cz" target="_blank">Git</a>
+ verwaltet. Ein Howto zum Arbeiten mit Git findet man
+ in unserem <a href="http://wiki.ipfire.org/de/development/git" target="_blank">Wiki</a>.
+ <br />
+ Den Source-Code findet man unter: <a href="http://git.ipfire.org/" target="_blank">http://git.ipfire.org/</a>
+ {% else %}
+ Our source code repository is managed by
+ <a href="http://git.or.cz" target="_blank">git</a>.
+ Your will find a howto to work with git in our
+ <a href="http://wiki.ipfire.org/en/development/git" target="_blank">wiki</a>.
+ <br />
+ You may find our source code on: <a href="http://git.ipfire.org/" target="_blank">http://git.ipfire.org/</a>
+ {% end %}
+ </p>
+ </div>
+ <br class="clear" />
+
+
+ <div class=post>
+ <h3>{{ _("source-code") }}</h3>
+ <p>
+ {% if lang == "de" %}
+ Die Sourcecode-Tarballs der im IPFire verwendeten Tools findet man unter
+ <a href="http://source.ipfire.org/" target="_target">http://source.ipfire.org/</a><br />
+ Alle Patches, die in der Distribution Verwendung finden, werden in einem
+ Git-Repository verwaltet (Siehe oben).
+ {% else %}
+ The source code tarballs of the tools used in IPFire are available on
+ <a href="http://source.ipfire.org/" target="_target">http://source.ipfire.org/</a>.<br />
+ All patches that are used in our distribution are stored in a git repository (see above).
+ {% end %}
+ </p>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("bugtracker") }}</h3>
+ <img src="http://bugtracker.ipfire.org/images/mantis_logo.gif" class="floatTL" width="80" alt="{{ _("bugtracker") }}" />
+ <p>
+ {% if lang == "de" %}
+ Im <a href="http://bugtracker.ipfire.org" target="_blank">Bugtracker</a> findet man bekannte Fehler.<br />
+ Solltet ihr also einen Fehler oder auch Funktionsvorschlag haben so könnt ihr uns über den Bugtracker
+ dies mitteilen. Für die Entwicklung ist es wichtig, dass es ausführliche Bug-Reports gibt,
+ die dann rasch bearbeitet werden können.
+ {% else %}
+ We manage all issues in our <a href="http://bugtracker.ipfire.org" target="_blank">bugtracker</a>.<br />
+ Should you have a bug or feature proposal you can tell us about it by posting
+ to the bugtracker. It is important for development to create a detailed bug reports so that
+ we can fix them fastly.
+ {% end %}
+ </p>
+ </div>
+ <br class="clear" />
+
+
+ <div class=post>
+ <h3>{{ _("HowTos") }}</h3>
+ <p>
+ {% if lang == "de" %}
+ Im Wiki befinden sich viele weitere Howtos hier einmal die wichtigsten rund ums Entwickeln.
+ <div class=pr_li>
+ <ul>
+ <li><a href="http://wiki.ipfire.org/de/development/build" target="_blank">Building IPFire</a></li>
+ <li><a href="http://wiki.ipfire.org/de/development/addon" target="_blank">Building Addon</a></li>
+ <li><a href="http://wiki.ipfire.org/de/development/language" target="_blank">Creating language file</a></li>
+ </ul>
+ </div>
+ {% else %}
+ In the wiki there are many other howtos here folowing the important ons for development.
+ <div class=pr_li>
+ <ul>
+ <li><a href="http://wiki.ipfire.org/en/development/build" target="_blank">Building IPFire</a></li>
+ <li><a href="http://wiki.ipfire.org/en/development/addon" target="_blank">Building Addon</a></li>
+ <li><a href="http://wiki.ipfire.org/en/development/language" target="_blank">Creating language file</a></li>
+ </ul>
+ </div>
+ {% end %}
+ </p>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("IPFire 3.x") }}</h3>
+ <p>
+ {% if lang == "de" %}
+ Unser nächstes Ziel ist die Entwicklung einer völlig neuen und komplett redesignten IPFire Version 3.<br />
+ In der <a href="downloads/development" target="_blank">Download-Sektion</a>
+ gibt es aktuelle Entwicklungsversionen zum herunterladen.
+ <div class=pr_li>
+ <ul>
+ <li><a href="http://wiki.ipfire.org/de/development/3.0" target="_blank">Roadmap von IPFire 3.x</a></li>
+ </ul>
+ </div>
+ {% else %}
+ Our next goal is to develop a completely new and redesigned IPFire version 3.<br />
+ In the <a href="downloads/development" target="_blank">download section</a>
+ you can get a curent development version.
+ <div class=pr_li>
+ <ul>
+ <li><a href="http://wiki.ipfire.org/en/development/3.0" target="_blank">Roadmap of IPFire 3.x</a></li>
+ </ul>
+ </div>
+ {% end %}
+ </div>
+
+
+{% end block %}
+
+{% block sidebar %}
+ <h4>{{ _("Development Area") }}</h4>
+ <ul class="links">
+ <li class="first"><a href="#{{ _("git") }}">{{ _("git") }}</a></li>
+ <li><a href="#{{ _("source-code") }}">{{ _("source-code") }}</a></li>
+ <li><a href="#{{ _("bugtracker") }}">{{ _("bugtracker") }}</a></li>
+ <li><a href="#{{ _("IPFire 3.x") }}">{{ _("IPFire 3.x") }}</a></li>
+ <li>
+ <a href="http://www.ohloh.net/projects/compare?metric=Activity&project_0=IPFire&project_1=Smoothwall&project_2=IPCop+Firewall" target="_blank">
+ {% if lang == "de" %}
+ IPFire im Vergleich mit IPCop und Smoothwall auf ohloh.net
+ {% else %}
+ Comparison of IPFire to IPCop and Smoothwall on ohloh.net
+ {% end %}
+ </a>
+ </li>
+ </ul>
+
+
+
+ {{ modules.SidebarBanner(banner) }}
+
+{% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Donation") }}{% end block %}
+
+
+{% block content %}
+
+
+ <div class=post>
+ <h3>{{ _("Donation") }}</h3>
+ <img src="{{ static_url("images/page_icons/donation.png") }}") }}" class="floatTR" border="0" alt="{{ _("Donation") }}" />
+ <p>
+ {% if lang == "de" %}
+ Mit jeder Spende und sei sie noch so klein unterstützen sie dieses Projekt sehr.
+ {% else %}
+ With each donation, and if with small ones you support this project.
+ {% end %}
+ </p>
+ </div>
+ <br class="clear" />
+
+ {% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Imprint") }}{% end block %}
+
+{% block content %}
+
+ <div class=post>
+ <h3>{{ _("Imprint") }}</h3>
+ <img src="{{ static_url("images/page_icons/imprint.png") }}" class="floatTR" border="0" alt="{{ _("Imprint") }}" />
+
+ {% if lang == "de" %}
+ <p>
+ Dieses Projekt ist ein Open-Source-Projekt und verfolgt keine kommerziellen Ziele.
+ </p>
+
+ <p>
+ <strong>Verantwortliche im Sinne von § 5 TMG, § 55 RfStV:</strong>
+ <br />
+
+ Michael Tremer (<a href="mailto:michael@ipfire.org">michael@ipfire.org</a>)<br />
+ Gerhardstrasse 8<br />
+ 45711 Datteln<br /><br />
+
+ Christian Schmidt (<a href="mailto:maniacikarus@ipfire.org">maniacikarus@ipfire.org</a>)<br />
+ Mathildenstr. 25<br />
+ 90489 Nürnberg<br /><br />
+
+ </p>
+
+ <h4>Haftungsausschluss</h4>
+ <p>
+ <b>1. Inhalt des Onlineangebotes</b><br />
+ Der Autor übernimmt keinerlei Gewähr für die Aktualität, Korrektheit, Vollständigkeit
+ oder Qualität der bereitgestellten Informationen. Haftungsansprüche gegen den Autor,
+ welche sich auf Schäden materieller oder ideeller Art beziehen, die durch die Nutzung
+ oder Nichtnutzung der dargebotenen Informationen bzw. durch die Nutzung fehlerhafter
+ und unvollständiger Informationen verursacht wurden, sind grundsätzlich ausgeschlossen,
+ sofern seitens des Autors kein nachweislich vorsätzliches oder grob fahrlässiges
+ Verschulden vorliegt.<br />
+ Alle Angebote sind freibleibend und unverbindlich. Der Autor behält es sich ausdrücklich vor,
+ Teile der Seiten oder das gesamte Angebot ohne gesonderte Ankündigung zu verändern,
+ zu ergänzen, zu löschen oder die Veröffentlichung zeitweise oder endgültig einzustellen.
+ </p>
+
+ <p>
+ <b>2. Verweise und Links</b><br />
+ Bei direkten oder indirekten Verweisen auf fremde Internetseiten ("Links"),
+ die außerhalb des Verantwortungsbereiches des Autors liegen, würde eine
+ Haftungsverpflichtung ausschließlich in dem Fall in Kraft treten, in dem der
+ Autor von den Inhalten Kenntnis hat und es ihm technisch möglich und zumutbar wäre,
+ die Nutzung im Falle rechtswidriger Inhalte zu verhindern. <br />
+ Der Autor erklärt hiermit ausdrücklich, dass zum Zeitpunkt der Linksetzung keine
+ illegalen Inhalte auf den zu verlinkenden Seiten erkennbar waren.
+ Auf die aktuelle und zukünftige Gestaltung, die Inhalte oder die Urheberschaft
+ der gelinkten/verknüpften Seiten hat der Autor keinerlei Einfluss. Deshalb distanziert
+ er sich hiermit ausdrücklich von allen Inhalten aller gelinkten /verknüpften Seiten,
+ die nach der Linksetzung verändert wurden. Diese Feststellung gilt für alle innerhalb
+ des eigenen Internetangebotes gesetzten Links und Verweise sowie für Fremdeinträge
+ in vom Autor eingerichteten Gästebüchern, Diskussionsforen und Mailinglisten.
+ Für illegale, fehlerhafte oder unvollständige Inhalte und insbesondere für Schäden,
+ die aus der Nutzung oder Nichtnutzung solcherart dargebotener Informationen entstehen,
+ haftet allein der Anbieter der Seite, auf welche verwiesen wurde, nicht derjenige,
+ der über Links auf die jeweilige Veröffentlichung lediglich verweist.
+ </p>
+
+ <p>
+ <b>3. Urheber- und Kennzeichenrecht </b><br />
+ Der Autor ist bestrebt, in allen Publikationen die Urheberrechte der verwendeten Grafiken,
+ Tondokumente, Videosequenzen und Texte zu beachten, von ihm selbst erstellte Grafiken,
+ Tondokumente, Videosequenzen und Texte zu nutzen oder auf lizenzfreie Grafiken, Tondokumente,
+ Videosequenzen und Texte zurückzugreifen. <br />
+ Alle innerhalb des Internetangebotes genannten und ggf. durch Dritte geschützten Marken-
+ und Warenzeichen unterliegen uneingeschränkt den Bestimmungen des jeweils gültigen Kennzeichenrechts
+ und den Besitzrechten der jeweiligen eingetragenen Eigentümer. Allein aufgrund der bloßen Nennung
+ ist nicht der Schluss zu ziehen, dass Markenzeichen nicht durch Rechte Dritter geschützt sind! <br />
+ Das Copyright für veröffentlichte, vom Autor selbst erstellte Objekte bleibt allein beim Autor der Seiten.
+ Eine Vervielfältigung oder Verwendung solcher Grafiken, Tondokumente, Videosequenzen und Texte in
+ anderen elektronischen oder gedruckten Publikationen ist ohne ausdrückliche Zustimmung des Autors nicht gestattet.
+ </p>
+
+ <p>
+ <b>4. Datenschutz </b><br />
+ Sofern innerhalb des Internetangebotes die Möglichkeit zur Eingabe persönlicher oder geschäftlicher Daten
+ (Emailadressen, Namen, Anschriften) besteht, so erfolgt die Preisgabe dieser Daten seitens
+ des Nutzers auf ausdrücklich freiwilliger Basis. Die Inanspruchnahme und Bezahlung aller
+ angebotenen Dienste ist - soweit technisch möglich und zumutbar - auch ohne Angabe solcher Daten
+ bzw. unter Angabe anonymisierter Daten oder eines Pseudonyms gestattet. Die Nutzung der im Rahmen
+ des Impressums oder vergleichbarer Angaben veröffentlichten Kontaktdaten wie Postanschriften,
+ Telefon- und Faxnummern sowie Emailadressen durch Dritte zur Übersendung von nicht ausdrücklich
+ angeforderten Informationen ist nicht gestattet. Rechtliche Schritte gegen die Versender von
+ sogenannten Spam- Mails bei Verstössen gegen dieses Verbot sind ausdrücklich vorbehalten.
+ </p>
+
+ <p>
+ <b>5. Rechtswirksamkeit dieses Haftungsausschlusses </b><br />
+ Dieser Haftungsausschluss ist als Teil des Internetangebotes zu betrachten, von dem aus auf diese
+ Seite verwiesen wurde. Sofern Teile oder einzelne Formulierungen dieses Textes der geltenden
+ Rechtslage nicht, nicht mehr oder nicht vollständig entsprechen sollten, bleiben die übrigen
+ Teile des Dokumentes in ihrem Inhalt und ihrer Gültigkeit davon unberührt.
+ </p>
+
+ <p>
+ Dieses Impressum gilt für alle mit dem IPFire-Projekt verbundenen Webseiten.
+ </p>
+
+ {% else %}
+ <p>
+ Because of the fact that the people who started this project are living
+ in Germany and the German law demands it. This side is only available in german language,
+ so please have a look at the <a href="{{ lang_link("de") }}">german legal notes</a>.
+ </p>
+ {% end %}
+ </div>
+ <br class="clear" />
+
+{% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Public Relations") }}{% end block %}
+
+
+{% block content %}
+
+
+ <div class=post>
+ <h3>{{ _("Public Relations") }}</h3>
+ <img src="{{ static_url("images/page_icons/pr.png") }}") }}" class="floatTR" border="0" alt="{{ _("Public Relations") }}" />
+ <p>
+ {% if lang == "de" %}
+ Euer Ansprechpartner für die Bereiche Presse, allgemeine Öffentlichkeitsarbeit und Sponsoring:
+ {% else %}
+ Your contact person for the fields press, general public relations and sponsorship:
+ {% end %}
+ <br /><br />
+ Markus Krüger
+ <img src="http://wiki.ipfire.org/lib/tpl/ipfire3-1/images/mail_icon.gif" align="absmiddle"/><a href="mailto:markus.krueger@ipfire.org">eMail</a><br />
+ Kollegstraße 2 / 432<br />
+ 44801 Bochum<br />
+ {% if lang != "de" %}
+ West Germany
+ {% end %}
+ </p>
+ </div>
+ <br class="clear" />
+
+ <div class=post>
+ <h3>{{ _("Press") }}</h3>
+ <p>
+ <h4>{{ _("Press kit") }}</h4>
+
+ {% if lang == "de" %}
+ <p>
+ Hier findet hier eine groß\9fe Auswahl an Informationen rund um das Projekt IPFire.
+ </p>
+ {% else %}
+ <p>
+ Here you will find a large selection of information about the project IPFire.
+ </p>
+ {% end %}
+ <br />
+
+ <h4>{{ _("Logos and print artworks") }}</h4>
+ <p>
+ <div class=pr_li>
+ <ul>
+ <li>{{ _("<strong>Print</strong> media") }}:</li>
+ <ul>
+ {% if lang == "de" %}
+ <p>
+ <em>Bilder von Tim - hier rein</em>
+ </p>
+ {% else %}
+ <p>
+ <em>Picture made by Tim - put in here</em>
+ </p>
+ {% end %}
+ </ul>
+ <li>{{ _("<strong>Online</strong> media") }}:</li>
+ <ul>
+ <li><img src="{{ static_url("images/tux/ipfire_tux_16x16.png") }}" align="bottom" border= "0"/>
+ <img src="{{ static_url("images/tux/ipfire_tux_32x32.png") }}" align="bottom" border= "0"/>
+ <img src="{{ static_url("images/tux/ipfire_tux_64x64.png") }}" align="bottom" border= "0"/>
+ <img src="{{ static_url("images/tux/ipfire_tux_128x128.png") }}" align="bottom" border= "0"/>
+ <br /><a href="{{ static_url("images/tux/ipfire_tux_16x16.png") }}") }}" target="_blank" border="0">
+ ipfire.png (16 x 16)</a>
+ <br /><a href="{{ static_url("images/tux/ipfire_tux_32x32.png") }}") }}" target="_blank" border="0">
+ ipfire.png (32 x 32)</a>
+ <br /><a href="{{ static_url("images/tux/ipfire_tux_64x64.png") }}") }}" target="_blank" border="0">
+ ipfire.png (64 x 64)</a>
+ <br /><a href="{{ static_url("images/tux/ipfire_tux_128x128.png") }}") }}" target="_blank" border="0">
+ ipfire.png (128 x 128)</a>
+ <br /><a href="{{ static_url("images/tux/ipfire_tux_256x256.png") }}") }}" target="_blank" border="0">
+ ipfire.png (256 x 256)</a>
+ <br /><a href="{{ static_url("images/tux/ipfire_tux_512x512.png") }}") }}" target="_blank" border="0">
+ ipfire.png (512 x 512)</a></li>
+ </ul>
+ </ul>
+ </div>
+ </p>
+ </p>
+ </div>
+
+ <div class=post>
+ <h3>{{ _("IPFire in the press") }}</h3>
+ <p>
+ {% if lang == "de" %}
+ Hier findet ihr einige Artikel über IPFire in der internationalen Presse.<br />
+ Wenn ihr neue Artikel über IPFire kennt die hier noch nicht aufgelistet sind, sendet uns diese an die oben angegeben Adresse,
+ damit diese hinzugefügt werden können.
+ {% else %}
+ Below are recent articles about IPFire in the international press.<br />
+ If you know of any news stories featuring IPFire that we have not listed here, please send details to the contact given above
+ so that we can include them.
+ {% end %}
+ </p>
+ <br />
+ <div class=pr_li>
+ <ul>
+ <li>{{ _("Press") }}:</li>
+ <ul>
+ <li>www.pro-linux.de: <a href="http://www.pro-linux.de/NB3/artikel/2/613/ipfire.html" target="_blank">
+ Vorstellung von IPFire</a>,
+ <a href="http://www.pro-linux.de/NB3/news/1/14360/1,ipfire-25-freigegeben.html" target="_blank">
+ IPFire 2.5 freigegeben</a>,
+ <a href="http://www.pro-linux.de/NB3/news/1/13436/1,ipfire-23-freigegeben.html" target="_blank">
+ IPFire 2.3 freigegeben</a></li>
+ <li>www.heise.de: <a href="http://www.heise.de/software/download/ipfire/47736a" target="_blank">
+ Artikel aus c't 20/2009</a></li>
+ <li>www.securebase.at: <a href="http://www.securebase.at/software/application-gateways/ipfire-schutz-gegen-jegliche-art-von-spyware-malware-und-sonstigen-hacker-aktivitaten" target="_blank">Schutz gegen jegliche Art von Spyware, Malware...</a></li>
+ <li>www.techmonkey.de: <a href="http://www.techmonkey.de/2008/09/15/ipfire-der-nachste-star-am-soho-himmel/" target="_blank">
+ Der nächste Star am SOHO Himmel?</a>,
+ <a href="http://www.techmonkey.de/2009/06/24/endlich-ipfire-2-5-erschien" target="_blank">Endlich!
+ IPFire 2.5 erschienen</a>
+ <li>www.pcwelt.de: <a href="http://www.pcwelt.de/start/sicherheit/firewall/news/187759/ipfire_auf_version_23_aktualisiert/"
+ target="_blank">IPFire auf Version 2.3 aktualisiert</a></li>
+ <li>www.lintelligence.de: <a href="http://www.lintelligence.de/news/1026" target="_blank">IPFire 2.1</a></li>
+ <li>www.h-online.com: <a href="http://www.h-online.com/newsticker/news/item/IPFire-the-Lean-Linux-firewall-738055.html"
+ target="_blank">IPFire, the Lean Linux firewall</a></li>
+ <li>www.4reackt.net: <a href="http://www.4reackt.net/programas-linux-rpms/5303-ipfire-v2-1-a.html"
+ target="_blank">IPFire v2.1</a></li>
+ </ul>
+ <li>Blogs:</li>
+ <ul>
+ <li>linuxmini.blogspot.com: <a href="http://linuxmini.blogspot.com/2007/10/ipfire-free-firewall-for-your-home-or.html"
+ target="_blank">Free firewall for your home or SOHO</a></li>
+ <li>www.ffoutpost.net: <a href="http://www.ffoutpost.net/2009/09/01/ipfire-initial-setup" target="_blank">
+ IPFire Initial Setup</a>,
+ <a href="http://www.ffoutpost.net/2009/09/15/ipfire-wireless-blue-access-setup" target="_blank">IPFire
+ Wireless (Blue Access) Setup</a></li>
+ </ul>
+ <ul>
+ </div>
+ </div>
+
+ <div class=post>
+ <h3>{{ _("Sponsoring") }}</h3>
+ {% if lang == "de" %}
+ <p>
+ Da das Projekt mittlerweile auf eine stattliche Größe angewachsen ist,
+ sind wir in vielen Bereichen auf Eure Hilfe angewiesen.
+ Allen voran ist die (Server-)Infrastuktur für das Aufrechterhalten der
+ Webseite inklusive des Wikis und der Foren zu nennen.
+ Auch für genügend Platz und Bandbreite zum erstellen, 'konservieren' und
+ verteilen der Nightly-builds muss gesorgt werden.
+ </p><br />
+ <p>
+ Falls ihr das Projekt also unterstützen möchtet und zufällig einen
+ Bladeserver 'übrig' habt und/oder einen freien Platz für's Server-Housing
+ mit entsprechender Bandbreite kostenlos zur Verfügung stellen wollt,
+ werden wir gerne auf Eure Angebote eingehen.
+ (Unsere Entwickler freuen sich auch immer über neue Hardware auf der
+ ausgiebig getestet werden kann.)
+ </p><br />
+ <p>
+ Abgesehen von der Hardware sind wir auch immer auf der Suche nach
+ helfenden Händen für die IPFire-Community.
+ Besonders gefragt sind Personen, die sich mit Linux auskennen und die
+ neuesten Funktionen und Addons testen und Fehler melden,
+ aktive Forenmoderatoren, Wiki-Dokumentatoren sowie Web- und Grafikdesigner.
+ </p><br />
+ <p>
+ Um die IPFire-Community zu unterstützen, melden Sie sich einfach im <a href="http://forum.ipfire.org">Forum</a>
+ oder im IRC-Channel <a href="http://webchat.freenode.net/?channels=ipfire" target="_blank">#ipfire</a>
+ auf irc.freenode.net.
+ </p><br />
+ <p>
+ Momentan besonders dringend benötigt werden:
+ <div class="li_pr">
+ <ul>
+ <li>Neuer Server mit ausreichend Platz</li>
+ <li>und Hosting/Housingpartner mit hoher Bandbreite</li>
+ <br />
+ <li>Spenden für die <a href="cebit">CeBIT 2010</a></li>
+ </ul>
+ </div>
+ </p>
+ {% else %}
+ <p>
+ <em>General information about sponsorshop and partners - need to be translated </em>
+ </p>
+ {% end %}
+ <br />
+
+ <h4>{{ _("friends of ipfire") }}</h4>
+ <p>
+ {% if lang == "de" %}
+ Die folgenden User ermöglichen dem Projekt die Nutzung ihrer persönlichen Server (<a href="downloads/mirrors">Mirror</a>,
+ Build und Root Server).
+ An dieser Stelle möchten wir uns bei Allen für ihre Unterstützung bedanken. (Liste in alphabetischer Reihenfolge.)
+ {% else %}
+ The following users are supporting the project by sharing their personal server (<a href="downloads/mirrors">mirror</a>,
+ build, and root servers).
+ At this point we would like to thank all for their help. (List in alphabetical order.)
+ {% end %}
+ <div class=pr_li>
+ <ul>
+ <li>Kim Barthel: <a href="http://www.kbarthel.de" target="_blank">www.kbarthel.de</a></li>
+ <li>Peter Schaelchli: <a href="http://www.scp-systems.ch" target="_blank">www.scp-systems.ch</a></li>
+ <li>Ronald Wiesinger: <a href="http://www.rowie.at" target="_blank">www.rowie.at</a></li>
+ <li>Sebastian Winter</li>
+ </ul>
+ </div>
+ </p>
+ </div>
+
+
+
+{% end block %}
+
+{% block sidebar %}
+ <h4>Public <span>relations</span></h4>
+ <ul class="links">
+ <li class="first"><a href="#{{ _("Press") }}">{{ _("Press") }}</a></li>
+ <li><a href="#{{ _("Press kit") }}">{{ _("Press kit") }}</a></li>
+ <li><a href="#{{ _("Logos and print artworks") }}">{{ _("Logos and print artworks") }}</a></li>
+ <li class="first"><a href="#{{ _("IPFire in the press") }}">{{ _("IPFire in the press") }}</a></li>
+ <li><a href="#{{ _("Sponsoring") }}">{{ _("Sponsoring") }}</a></li>
+ <li><a href="#{{ _("friends of ipfire") }}">{{ _("friends of ipfire") }}</a></li>
+ </ul>
+{% end block %}
--- /dev/null
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Screenshots") }}{% end block %}
+
+{% block content %}
+
+
+ <div class=post>
+ <h3>{{ _("Sceenshots") }}</h3>
+ <img src="{{ static_url("images/page_icons/screenshots.png") }}" class="floatTR" border="0" alt="{{ _("Sceenshots") }}" />
+ <p>
+ {% if lang == "de" %}
+ Hier findet ihr einen Einblick in das IPFire Webinterface.
+ {% else %}
+ Here you will find an insight into the IPFire webinterface.
+ {% end %}
+ </p>
+ </div>
+
+ <br class="clear" />
+ <div class=post>
+ <h3>{{ _("System") }}</h3>
+ <div id="screenshots">
+
+ <a href="{{ static_url("images/screenshots/index_%s.png" % lang) }}" title="{{ _("Home") }}"><img src="{{ static_url("images/screenshots/index_%s_tn.png" % lang) }}" border="0" alt="{{ _("Home") }}" /></a>
+
+ <a href="{{ static_url("images/screenshots/backup_%s.png" % lang) }}" title="{{ _("Backup") }}"><img src="{{ static_url("images/screenshots/backup_%s_tn.png" % lang) }}" border="0" alt="{{ _("Backup") }}" /></a>
+ </div>
+ </div>
+
+ <div class=post>
+ <h3>{{ _("Status") }}</h3>
+ <div id="screenshots">
+
+ <a href={{ static_url("images/screenshots/services_%s.png" % lang) }}" title="{{ _("Services") }}"><img src={{ static_url("images/screenshots/services_%s_tn.png" % lang) }}" border="0" alt="{{ _("Services") }}"></a>
+
+ <a href={{ static_url("images/screenshots/networkother_%s.png" % lang) }}" title="{{ _("Network (other)") }}"><img src={{ static_url("images/screenshots/networkother_%s_tn.png" % lang) }}" border="0" alt="Network (other)"></a>
+
+ <a href={{ static_url("images/screenshots/connections_%s.png" % lang) }}" title="{{ _("Connections") }}"><img src={{ static_url("images/screenshots/connections_%s_tn.png" % lang) }}" border="0" alt="{{ _("Connections") }}"></a>
+ </div>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("Network") }}</h3>
+ <div id="screenshots">
+
+ <a href={{ static_url("images/screenshots/dhcp_%s.png" % lang) }}" title="{{ _("DHCP Server") }}"><img src={{ static_url("images/screenshots/dhcp_%s_tn.png" % lang) }}" border="0" alt="{{ _("DHCP Server") }}"></a>
+ </div>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("Services") }}</h3>
+ <div id="screenshots">
+
+ <a href={{ static_url("images/screenshots/ipsec_%s.png" % lang) }}" title="{{ _("IPSec") }}"><img src={{ static_url("images/screenshots/ipsec_%s_tn.png" % lang) }}" border="0" alt="{{ _("IPSec") }}"></a>
+
+ <a href={{ static_url("images/screenshots/qos_%s.png" % lang) }}" title="{{ _("Quality of Service") }}"><img src={{ static_url("images/screenshots/qos_%s_tn.png" % lang) }}" border="0" alt="{{ _("Quality of Service") }}"></a>
+ </div>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("Firewall") }}</h3>
+ <div id="screenshots">
+
+ <a href={{ static_url("images/screenshots/outgoing_fw_%s.png" % lang) }}" title="{{ _("Outgoing Firewall") }}"><img src={{ static_url("images/screenshots/outgoing_fw_%s_tn.png" % lang) }}" border="0" alt="{{ _("Outgoing Firewall") }}"></a>
+ </div>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("IPFire") }}</h3>
+ <div id="screenshots">
+
+ <a href={{ static_url("images/screenshots/pakfire_%s.png" % lang) }}" title="{{ _("Pakfire") }}"><img src={{ static_url("images/screenshots/pakfire_%s_tn.png" % lang) }}" border="0" alt="{{ _("Pakfire") }}"></a>
+
+ <a href={{ static_url("images/screenshots/samba_%s.png" % lang) }}" title="{{ _("Samba") }}"><img src={{ static_url("images/screenshots/samba_%s_tn.png" % lang) }}" border="0" alt="{{ _("Samba") }}"></a>
+ </div>
+ </div>
+
+
+ <div class=post>
+ <h3>{{ _("Logs") }}</h3>
+ <div id="screenshots">
+
+ <a href={{ static_url("images/screenshots/fwlog_ip_%s.png" % lang) }}" title="{{ _("Fw-Logdgraphs (IP)") }}"><img src={{ static_url("images/screenshots/fwlog_ip_%s_tn.png" % lang) }}" border="0" alt="{{ _("Fw-Logdgraphs (IP)") }}"></a>
+
+ <a href={{ static_url("images/screenshots/proxy_%s.png" % lang) }}" title="{{ _("Proxy Reports") }}"><img src={{ static_url("images/screenshots/proxy_%s_tn.png" % lang) }}" border="0" alt="{{ _("Proxy Reports") }}"></a>
+ </div>
+ </div>
+
+{% end block %}
+
+{% block sidebar %}
+ <h4><span>{{ _("Screenshot") }}</span> list</h4>
+ <ul class="links">
+ <li class="first"><a href="#{{ _("System") }}">{{ _("System") }}</a></li>
+ <li><a href="#{{ _("Status") }}">{{ _("Status") }}</a></li>
+ <li><a href="#{{ _("Network") }}">{{ _("Network") }}</a></li>
+ <li><a href="#{{ _("Services") }}">{{ _("Services") }}</a></li>
+ <li><a href="#{{ _("Firewall") }}">{{ _("Firewall") }}</a></li>
+ <li><a href="#{{ _("IPFire") }}">{{ _("IPFire") }}</a></li>
+ <li><a href="#{{ _("Logs") }}">{{ _("Logs") }}</a></li>
+ </ul>
+ {{ modules.SidebarBanner(banner) }}
+
+{% end block %}
+
+{% block javascript %}
+ <script type="text/javascript" src="{{ static_url("js/jquery.lightbox.min.js") }}"></script>
+ <script type="text/javascript">
+ $(function() {
+ $("#screenshots a").lightBox();
+ });
+ </script>
+{% end block %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Translations") }}{% end block %}
+
+{% block content %}
+ <h3>IPFire {{ _("Translation Status") }}</h3>
+
+ <div id="tabs">
+ <ul>
+ {% for project in projects %}
+ <li>
+ <a href="#{{ project.id }}">{{ project.name }}</a>
+ </li>
+ {% end %}
+ </ul>
+ </div>
+
+ {% for project in projects %}
+ <div id="{{ project.id }}">
+ <p><strong>{{ _("Description") }}:</strong> {{ project.desc }}</p>
+ <br />
+ <table class="translate">
+ <tr>
+ <th>{{ _("Language") }}</th>
+ <th>{{ _("Translated") }}</th>
+ <th>{{ _("Untranslated") }}</th>
+ <th>{{ _("Fuzzy") }}</th>
+ <th>{{ _("Status") }}</th>
+ </tr>
+
+ {% for translation in project.translations %}
+ <tr>
+ <td class="lang"><img src="{{ static_url("images/flags/%s.png" % translation.code) }}"
+ alt="{{ translation.code }}" />{{ translation.lang }}</td>
+ <td>{{ translation.translated }}</td>
+ <td>{{ translation.untranslated }}</td>
+ <td>{{ translation.fuzzy }}</td>
+ <td>{{ translation.percent }}</td>
+ </tr>
+ {% end %}
+ </table>
+ {% end %}
+
+ <p class="right">
+ <strong>{{ _("Template") }}</strong> - {{ project.total_strings }} strings
+ </p>
+{% end block %}
+
+{% block javascript %}
+ <script type="text/javascript">
+ $(function() {
+ $("#tabs").tabs();
+ });
+ </script>
+{% end block %}
--- /dev/null
+"Alix image","Alix-Image"
+"An image that is meant to run on embedded devices.","Fertiges Image für Embedded-Geräte."
+"Arch","Arch"
+"Area","Bereich"
+"A ready-to-run image for Xen.","Schlüsselfertiges Xen-Image."
+"Begin download","Download starten"
+"by","von"
+"CeBIT-Donation","CeBIT-Spende"
+"Cluster's CPU load","Prozessorauslastung des Clusters"
+"Connections","Verbindungen"
+"CPU-Load","CPU-Auslastung"
+"Current unstable","Entwicklungsversion"
+"Current version","Aktuelle Version"
+"Description","Beschreibung"
+"Development","Entwicklung"
+"DHCP Server","DHCP-Server"
+"Download file","Datei herunterladen"
+"Download the CD image from the torrent network.","Laden Sie das CD-Image über das Torrent Netzwerk."
+"File","Datei"
+"Firewall","Firewall"
+"Fuzzy","Fuzzy"
+"Fw-Logdgraphs (IP)","Fw-Logdgraphs (IP)"
+"Got that information from <em>%s</em> within %.2f second(s).","Dauer der Abfrage von <em>%s</em>: %.2f Sekunde(n)."
+"Home","Startseite"
+"If the floppy image doesn't work, use this image instead.","USB-Stick-Image als Harddisk formatiert."
+"imprint","Impressum"
+"Installable CD image","Bootbares CD-Image"
+"Install IPFire from a floppy-formated USB key.","Installationsimage für USB-Sticks als Floppy formatiert."
+"IPFire in the press","IPFire in der Presse"
+"IPSec","IPSec"
+"Job load","Job-Auslastung"
+"Jobs","Jobs"
+"Language","Sprache"
+"Logos and print artworks","Logos und Druckvorlagen"
+"More security for your network","mehr sicherheit für Ihr netzwerk"
+"Name","Name"
+"Network","Netzwerk"
+"Network (other)","Netzwerk (sonstige)"
+"Number of nodes","Anzahl der Knoten"
+"Other download options","Weitere Downloadoptionen"
+"Outgoing Firewall","Ausgehende Firewall"
+"Pakfire","Pakfire"
+"Pregenerated Xen image","Xen-Image"
+"Press kit","Pressemappe"
+"Press","Presse"
+"Previous posts >>","Vorherige Einträge >>"
+"Proxy Reports","Proxyberichte"
+"Public Relations","Public Relations"
+"Quality of Service","Quality of Service"
+"<strong>release</strong> information","<strong>Release</strong>informationen"
+"Release","Release"
+"Samba","Samba"
+"See all torrents...","Alle Torrent-Downloads anzeigen..."
+"See development releases...","Entwicklungsversionen anzeigen..."
+"See older downloads...","Ältere Downloads anzeigen..."
+"Services","Dienste"
+"Sponsoring","Sponsoring"
+"Status","Status"
+"<strong>Online</strong> media","<strong>Online</strong>medien"
+"<strong>Print</strong> media","<strong>Print</strong>medien"
+"System","System"
+"Template","Vorlage"
+"Torrent file","Torrent-Download"
+"Translated","Ãœbersetzt"
+"Translation Status","Übersetzungsüberblick"
+"Untranslated","Nicht übersetzt"
+"USB FDD image","USB-Floppy-Image"
+"USB HDD image","USB-Harddisk-Image"
+"Use this image to burn a CD and install IPFire from it.","Brennen Sie dieses Image und booten Sie die Installation davon."
+"Owner (Hostname)","Eigentümer (Hostname)"
+"Priority","Priorität"
+"Location","Standort"
+"Latency","Latenz"
+"Legend","Legende"
+"Server is reachable","Server ist erreichbar"
+"Server is unreachable","Server ist nicht erreichbar"
+"Get back to latest stable downloads.","Zurück zur aktuellen Version."
+"Here you will find the downloads for the version","Hier findet ihr die Downloads für die Version"
+"These are the ancient downloads of IPFire. They are just saved for historical reasons and should not be used in a productive environment.","Dies sind veraltete Downloads von IPFire. Sie sind nur aus historischen Gründen gespeichert und sollten nicht mehr in einer produktiven Umgebung eingesetzt werden."
+"Donation","Spende"
+"Development Area","Entwicklungsbereich"
+"See a list of mirrors...","Liste der Mirror-Server anzeigen..."
+"Flash image where a serial console is enabled by default.","Flash-Image mit eingeschalteter serieller Konsole."
+"Flash image","Flash-Image"
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import os
-import cgi
-import time
-
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-
-from http import HTTPResponse, WebError
-
-import info
-import lang
-import menu
-
-class Data:
- def __init__(self):
- self.output = ""
-
- def w(self, s):
- self.output += "%s\n" % s
-
- write = w
-
- def __call__(self):
- return self.output
-
-
-class Page(object):
- def __init__(self):
- self.io = StringIO.StringIO()
-
- self.info = info.Info()
- self.langs = lang.Languages()
- self.menu = menu.Menu(self.langs.current)
- self.site = self.title = cgi.FieldStorage().getfirst("site", default="index")
-
- self.content = None
- self.javascript = None
- self.sidebar = None
-
- @property
- def data(self):
- ret = { "content" : "",
- "javascript": "",
- "lang" : self.langs.current,
- "languages" : self.langs.menu(self.site),
- "menu" : self.menu(),
- "name" : self.info["name"],
- "server" : os.environ["SERVER_NAME"].replace("ipfire", "<span>ipfire</span>"),
- "sidebar" : "",
- "slogan" : self.info["slogan"],
- "sname" : self.info["sname"],
- "title" : "%s - %s" % (os.environ["SERVER_NAME"], self.title,),
- "year" : time.strftime("%Y"),}
-
- if self.content:
- ret["content"] = self.content(self.langs.current)
- if self.javascript:
- ret["javascript"] = self.javascript(self.langs.current)
- if self.sidebar:
- ret["sidebar"] = self.sidebar(self.langs.current)
-
- return ret
-
- def include(self, file):
- f = open(file)
- output = f.read()
- f.close()
- self.io.write(output % self.data)
-
- def __call__(self):
- type = "text/html"
- try:
- if self.title.endswith(".rss"):
- self.include("rss.inc")
- type = "application/rss+xml"
- else:
- self.include("template.inc")
- code = 200
- except WebError:
- code = 500
- h = HTTPResponse(code, type=type)
- h.execute(self.io.getvalue())
-
-
-class Content(Data):
- def __init__(self):
- Data.__init__(self)
-
- def content(self):
- self.w("""<h3>Test Page</h3>
- <p>Lorem ipsum dolor sit amet, consectetuer sadipscing elitr,
- sed diam nonumy eirmod tempor invidunt ut labore et dolore magna
- aliquyam erat, sed diam voluptua. At vero eos et accusam et justo
- duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
- sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
- consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt
- ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero
- eos et accusam et justo duo dolores et ea rebum. Stet clita kasd
- gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
- nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
- sed diam voluptua. At vero eos et accusam et justo duo dolores et ea
- rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
- ipsum dolor sit amet.</p>""")
-
- b = Box("Test box one", "Subtitle of box")
- b.write("""<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit
- esse molestie consequat, vel illum dolore eu feugiat nulla facilisis
- at vero eros et accumsan et iusto odio dignissim qui blandit praesent
- luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
- nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat
- volutpat.</p>""")
- self.w(b())
-
- b = Box("Test box two", "Subtitle of box")
- b.write("""<p>Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
- suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem
- vel eum iriure dolor in hendrerit in vulputate velit esse molestie
- consequat, vel illum dolore eu feugiat nulla facilisis at vero eros
- et accumsan et iusto odio dignissim qui blandit praesent luptatum
- zzril delenit augue duis dolore te feugait nulla facilisi.</p>""")
- self.w(b())
-
- def __call__(self, lang="en"):
- self.content()
- return Data.__call__(self)
+++ /dev/null
-#!/usr/bin/python
-
-import random
-
-from json import Json
-
-class Banners(Json):
- def __init__(self, lang="en"):
- self.lang = lang
- Json.__init__(self, "banners.json")
-
- def random(self):
- banner = random.choice(self.json.values())
- return banner
-
+++ /dev/null
-#!/usr/bin/python
-
-from web import Data
-from banners import Banners
-from info import Info
-
-class Box(Data):
- def __init__(self, headline, subtitle=""):
- Data.__init__(self)
- self.w("""<div class="post"><a name="%s"></a><h3>%s</h3>""" % (headline,headline,))
- if subtitle:
- self.w("""<div class="post_info">%s</div>""" % (subtitle,))
-
- def __call__(self):
- self.w("""<br class="clear" /></div>""")
- return Data.__call__(self)
-
-class Sidebar(Data):
- def __init__(self):
- Data.__init__(self)
-
- def content(self, lang):
- banners = Banners()
- self.w("""<h4>%(title)s</h4><a href="%(link)s" target="_blank">
- <img class="banner" src="%(uri)s" /></a>""" % banners.random())
-
- def __call__(self, lang):
- self.content(lang)
- return Data.__call__(self)
-
-class Releases(Data):
- def __init__(self):
- Data.__init__(self)
-
- def content(self, lang):
- info = Info()
- if lang == "de":
- self.write("""<h4><span>release</span> informationen</h4>
- <p><strong>Aktuelle Version</strong>:<br />%(stable)s</p>
- <p><strong>Testversionen</strong>:<br />%(testing)s</p>
- """ % info["releases"])
- else:
- self.write("""<h4><span>info</span>rmation</h4>
- <p><strong>Current version</strong>:<br />%(stable)s</p>
- <p><strong>Current unstables</strong>:<br />%(testing)s</p>
- """ % info["releases"])
-
- def __call__(self, lang):
- self.content(lang)
- return Data.__call__(self)
-
-class DevelopmentSidebar(Sidebar):
- def __init__(self):
- Sidebar.__init__(self)
-
- def __call__(self, lang):
- return Sidebar.__call__(self, lang)
-
- def content(self, lang):
- self.w("""<h4>Development Ressources</h4>
- <p> - <a href="cluster">Cluster</a> Monitoring<br />
- - Nightly <a href="builds">Builds</a><br />
- - <a href="source">Source</a> Code<br />
- - Pakfire <a href="pakfire3">Repositories</a><br />
- - <a href="translate">Localization</a> Status</p>
- """)
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-code2msg = { 200 : "OK",
- 302 : "Temporarily Moved",
- 404 : "Not found",
- 500 : "Internal Server Error", }
-
-class HTTPResponse:
- def __init__(self, code, header=None, type="text/html"):
- self.code = code
-
- print "Status: %s - %s" % (self.code, code2msg[self.code],)
- if self.code == 302:
- print "Pragma: no-cache"
- if type:
- print "Content-type: " + type
- if header:
- for (key, value,) in header:
- print "%s: %s" % (key, value,)
- print
-
- def execute(self, content=""):
- if self.code == 200:
- print content
-
-class WebError(Exception):
- pass
+++ /dev/null
-#!/usr/bin/python
-
-from json import Json
-
-class Info(Json):
- def __init__(self):
- Json.__init__(self, "info.json")
-
- def get(self, key):
- if not self.json.has_key(key):
- raise KeyError
- return self.json[key]
-
- __getitem__ = get
+++ /dev/null
-#!/usr/bin/python
-
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-
-class Javascript(object):
- def __init__(self, jquery=0, jqueryui=0):
- self.io = StringIO.StringIO()
-
- if jquery:
- self.io.write("""<script src="/include/jquery.min.js" type="text/javascript"></script>""")
-
- if jqueryui:
- self.io.write("""<script src="/include/jquery-ui.min.js" type="text/javascript"></script>""")
-
- def __call__(self, lang="en"):
- return self.io.getvalue()
-
- def jquery_plugin(self, plugin):
- self.io.write("""<script src="/include/jquery.%s.min.js" type="text/javascript"></script>""" % plugin)
-
- def write(self, s):
- self.io.write(s)
+++ /dev/null
-#!/usr/bin/python
-
-import simplejson as json
-
-class Json:
- def __init__(self, file):
- f = open(file)
- data = f.read()
- data = data.replace('\n', '') # Remove all \n
- data = data.replace('\t', ' ') # Remove all \t
- self.json = json.loads(data)
- f.close()
+++ /dev/null
-#!/usr/bin/python
-
-import locale
-import cgi
-
-lang2locale = { "de" : "de_DE.utf8",
- "en" : "en_US.utf8", }
-
-class Languages:
- def __init__(self, doc=""):
- self.available = []
-
- for lang in ("de", "en",):
- self.append(lang,)
-
- self.current = cgi.FieldStorage().getfirst("lang") or "en"
- if lang2locale.has_key(self.current):
- locale.setlocale(locale.LC_ALL, lang2locale[self.current])
-
- def append(self, lang):
- self.available.append(lang)
-
- def menu(self, doc):
- s = ""
- for lang in self.available:
- s += """<a href="/%(lang)s/%(doc)s"><img src="/images/%(lang)s.gif" alt="%(lang)s" /></a>""" % \
- { "lang" : lang, "doc" : doc, }
- return s
+++ /dev/null
-#!/usr/bin/python
-
-import os
-
-from json import Json
-
-class Menu(Json):
- def __init__(self, lang):
- self.lang = lang
- Json.__init__(self, "menu.json")
-
- def __call__(self):
- s = """<div id="menu"><ul>\n"""
- for item in self.json.values():
- item["active"] = ""
-
- # Grab language
- if type(item["name"]) == type({}):
- item["name"] = item["name"][self.lang]
-
- # Add language attribute to local uris
- if item["uri"].startswith("/"):
- item["uri"] = "/%s%s" % (self.lang, item["uri"],)
-
- if os.environ["REQUEST_URI"].endswith(item["uri"]):
- item["active"] = "class=\"active\""
-
- s += """<li><a href="%(uri)s" %(active)s>%(name)s</a></li>\n""" % item
- s += "</ul></div>"
- return s
+++ /dev/null
-#!/usr/bin/python
-
-from elements import Box
-from json import Json
-
-class News(Json):
- def __init__(self, limit=3):
- Json.__init__(self, "news.json")
- self.news = []
- for key in sorted(self.json.keys()):
- self.news.insert(0, self.json[key])
- if limit:
- self.news = self.news[:limit]
-
- def html(self, lang="en"):
- s = ""
- for item in self.news:
- for i in ("content", "subject",):
- if type(item[i]) == type({}):
- item[i] = item[i][lang]
- b = Box(item["subject"], "%(date)s - by %(author)s" % item)
- b.w(item["content"])
- if item["link"]:
- if lang == "en":
- b.w("""<p><a href="%(link)s" target="_blank">Read more.</a></p>""" % item)
- elif lang == "de":
- b.w("""<p><a href="%(link)s" target="_blank">Mehr Informationen.</a></p>""" % item)
- s += b()
- return s
-
- __call__ = html
-
- def headlines(self, lang="en"):
- headlines = []
- for item in self.news:
- if type(item["subject"]) == type({}):
- item["subject"] = item["subject"][lang]
- headlines.append((item["subject"],))
- return headlines
-
- def items(self):
- return self.news
--- /dev/null
+#!/usr/bin/python2.6
+
+import tornado.httpserver
+import tornado.ioloop
+
+from webapp import Application
+application = Application()
+
+if __name__ == "__main__":
+ http_server = tornado.httpserver.HTTPServer(application, xheaders=True)
+ http_server.listen(8001)
+
+ try:
+ tornado.ioloop.IOLoop.instance().start()
+ except KeyboardInterrupt:
+ # Shutdown mirror monitoring
+ from webapp.mirrors import mirrors
+ mirrors.shutdown()
+
+ raise
--- /dev/null
+#/usr/bin/python
+
+import os.path
+import simplejson
+
+simplejson._default_decoder = simplejson.JSONDecoder(encoding="latin-1")
+
+import tornado.locale
+import tornado.options
+import tornado.web
+
+from db import HashDatabase
+from handlers import *
+from ui_modules import *
+
+BASEDIR = os.path.join(os.path.dirname(__file__), "..")
+
+tornado.locale.load_translations(os.path.join(BASEDIR, "translations"))
+tornado.options.enable_pretty_logging()
+
+class Application(tornado.web.Application):
+ def __init__(self):
+ settings = dict(
+ cookie_secret = "aXBmaXJlY29va2llc2VjcmV0Cg==",
+ #debug = True,
+ gzip = True,
+ template_path = os.path.join(BASEDIR, "templates"),
+ ui_modules = {
+ "Build" : BuildModule,
+ "Menu" : MenuModule,
+ "MenuItem" : MenuItemModule,
+ "NewsItem" : NewsItemModule,
+ "ReleaseItem" : ReleaseItemModule,
+ "SidebarBanner" : SidebarBannerModule,
+ "SidebarItem" : SidebarItemModule,
+ "SidebarRelease" : SidebarReleaseModule,
+ },
+ xsrf_cookies = True,
+ )
+
+ tornado.web.Application.__init__(self, **settings)
+
+ # Initialize database connections
+ self.hash_db = HashDatabase()
+
+ self.settings["static_path"] = static_path = os.path.join(BASEDIR, "static")
+ static_handlers = [
+ (r"/static/(.*)", tornado.web.StaticFileHandler, dict(path = static_path)),
+ (r"/(favicon\.ico)", tornado.web.StaticFileHandler, dict(path = static_path)),
+ (r"/(robots\.txt)", tornado.web.StaticFileHandler, dict(path = static_path)),
+ ]
+
+ self.add_handlers(r"(dev|www)\.ipfire\.(at|org)", [
+ # Entry sites that lead the user to index
+ (r"/", MainHandler),
+ (r"/[A-Za-z]{2}/?", MainHandler),
+ #
+ (r"/[A-Za-z]{2}/index", IndexHandler),
+ (r"/[A-Za-z]{2}/news", NewsHandler),
+ (r"/[A-Za-z]{2}/builds", BuildHandler),
+ (r"/[A-Za-z]{2}/translations?", TranslationHandler),
+ # Download sites
+ (r"/[A-Za-z]{2}/downloads?", DownloadHandler),
+ (r"/[A-Za-z]{2}/downloads?/all", DownloadAllHandler),
+ (r"/[A-Za-z]{2}/downloads?/development", DownloadDevelopmentHandler),
+ (r"/[A-Za-z]{2}/downloads?/mirrors", DownloadMirrorHandler),
+ (r"/[A-Za-z]{2}/downloads?/torrents", DownloadTorrentHandler),
+ # API
+ (r"/api/cluster_info", ApiClusterInfoHandler),
+ # Always the last rule
+ (r"/[A-Za-z]{2}/(.*)", StaticHandler),
+ ] + static_handlers)
+
+ # download.ipfire.org
+ self.add_handlers(r"download\.ipfire\.org", [
+ (r"/", tornado.web.RedirectHandler, { "url" : "http://www.ipfire.org/" }),
+ (r"/(favicon\.ico)", tornado.web.StaticFileHandler, dict(path = static_path)),
+ (r"/(.*)", DownloadFileHandler),
+ ])
+
+ # source.ipfire.org
+ self.add_handlers(r"source\.ipfire\.org", [
+ (r"/", MainHandler),
+ (r"/[A-Za-z]{2}/?", MainHandler),
+ (r"/[A-Za-z]{2}/index", SourceHandler),
+ (r"(/source.*)", SourceDownloadHandler),
+ ] + static_handlers)
+
+ # torrent.ipfire.org
+ self.add_handlers(r"torrent\.ipfire\.org", [
+ (r"/", MainHandler),
+ (r"/[A-Za-z]{2}/?", MainHandler),
+ (r"/[A-Za-z]{2}/index", DownloadTorrentHandler),
+ ] + static_handlers)
+
+ # tracker.ipfire.org
+ self.add_handlers(r"tracker\.ipfire\.org", [
+ (r"/", MainHandler),
+ (r"/[A-Za-z]{2}/?", MainHandler),
+ (r"/[A-Za-z]{2}/index", DownloadTorrentHandler),
+ ] + static_handlers)
+
+ # ipfire.org
+ self.add_handlers(r".*", [
+ (r".*", tornado.web.RedirectHandler, { "url" : "http://www.ipfire.org" })
+ ])
+
+ def __del__(self):
+ from mirrors import mirrors
+ mirrors.stop()
--- /dev/null
+#!/usr/bin/python
+
+import random
+
+from helpers import Item, _stringify, json_loads
+
+class Banners(object):
+ def __init__(self, filename=None):
+ self.items = []
+
+ if filename:
+ self.load(filename)
+
+ def load(self, filename):
+ f = open(filename)
+ data = f.read()
+ f.close()
+
+ for item in json_loads(data):
+ self.items.append(Item(**_stringify(item)))
+
+ def get(self):
+ return random.choice(self.items)
+
+
+banners = Banners("banners.json")
--- /dev/null
+#!/usr/bin/python
+
+import os
+import time
+
+from helpers import size
+from info import info
+
+def find():
+ ret = []
+ for item in info["nightly_builds"]:
+ path = item.get("path", None)
+ if not path or not os.path.exists(path):
+ continue
+
+ for host in os.listdir(path):
+ for build in os.listdir(os.path.join(path, host)):
+ ret.append(Build(os.path.join(path, host, build)))
+
+ return ret
+
+class Build(object):
+ def __init__(self, path):
+ self.path = path
+
+ self.__buildinfo = None
+
+ @property
+ def buildinfo(self):
+ if not self.__buildinfo:
+ f = open(os.path.join(self.path, ".buildinfo"))
+ self.__buildinfo = f.readlines()
+ f.close()
+ return self.__buildinfo
+
+ def get(self, key):
+ key = key.upper() + "="
+ for line in self.buildinfo:
+ if line.startswith(key):
+ return line[len(key):].strip("\n")
+
+ @property
+ def build_host(self):
+ return self.get("hostname")
+
+ @property
+ def release(self):
+ return self.get("release")
+
+ @property
+ def time(self):
+ return time.localtime(float(self.get("date")))
+
+ @property
+ def date(self):
+ return time.strftime("%a, %Y-%m-%d %H:%M", self.time)
+
+ @property
+ def arch(self):
+ return self.get("arch")
+
+ @property
+ def iso(self):
+ return self.get("iso")
+
+ @property
+ def size(self):
+ return size(os.path.getsize(os.path.join(self.path, self.iso)))
+
+ @property
+ def packages(self):
+ path = "%s/packages_%s" % (self.path, self.arch,)
+ if not os.path.exists(path):
+ return []
+ return os.listdir(path)
+
+ @property
+ def pxe(self):
+ dir = "/srv/www/ipfire.org/pxe"
+ if not os.path.isdir(dir):
+ return ""
+
+ for iso in os.listdir(dir):
+ # Skip non-iso files
+ if not iso.endswith(".iso"):
+ continue
+ if os.readlink(os.path.join(dir, iso)) == os.path.join(self.path, self.iso):
+ return "[PXE]"
+ return ""
import os
import telnetlib
-import simplejson as json
-
class Node(object):
def __init__(self, hostname, address, arch, speed, jobcount, load, installing):
self.hostname = hostname
def __repr__(self):
return "<Node %s>" % self.hostname
+ def __cmp__(self, other):
+ return cmp(self.hostname, other.hostname)
+
def print_node(self):
print "Hostname : %s" % self.hostname
print " Address: %s" % self.address
node = Node(hostname, address, arch, speed, jobcount, load, installing)
ret.append(node)
- self._nodes = ret
+ self._nodes = sorted(ret)
return ret
@property
--- /dev/null
+#!/usr/bin/python
+
+import hashlib
+import sqlite3
+import os.path
+
+
+class HashDatabase(object):
+ def __init__(self):
+ self.conn = sqlite3.connect("/srv/www/ipfire.org/source/hashes.db")
+
+ def __del__(self):
+ self.conn.close()
+
+ def prepare(self):
+ c = self.conn.cursor()
+ c.execute("CREATE TABLE IF NOT EXISTS hashes(file, sha1)")
+ c.close()
+
+ def _save_hash(self, path, hash):
+ c = self.conn.cursor()
+ c.execute("INSERT INTO hashes VALUES('%s', '%s')" % (os.path.basename(path), hash))
+ c.close()
+
+ def get_hash(self, path):
+ c = self.conn.cursor()
+ c.execute("SELECT sha1 FROM hashes WHERE file = '%s'" % os.path.basename(path))
+
+ hash = c.fetchone()
+ c.close()
+
+ if not hash:
+ hash = self._calc_hash(path)
+ self._save_hash(path, hash)
+
+ if hash:
+ return "%s" % hash
+
+ def _calc_hash(self, path):
+ if not os.path.exists(path):
+ return
+
+ m = hashlib.sha1()
+ f = open(path)
+ m.update(f.read())
+ f.close()
+
+ return m.hexdigest()
--- /dev/null
+#!/usr/bin/python
+
+import datetime
+import httplib
+import mimetypes
+import operator
+import os
+import simplejson
+import stat
+import sqlite3
+import time
+import urlparse
+
+import tornado.httpclient
+import tornado.locale
+import tornado.web
+
+from banners import banners
+from helpers import size
+from info import info
+from mirrors import mirrors
+from news import news
+from releases import releases
+
+import builds
+import cluster
+import menu
+import translations
+#import uriel
+
+class BaseHandler(tornado.web.RequestHandler):
+ def get_user_locale(self):
+ uri = self.request.uri.split("/")
+ if len(uri) > 1:
+ for lang in tornado.locale.get_supported_locales(None):
+ if lang[:2] == uri[1]:
+ return tornado.locale.get(lang)
+
+ @property
+ def render_args(self):
+ return {
+ "banner" : banners.get(),
+ "lang" : self.locale.code[:2],
+ "langs" : [l[:2] for l in tornado.locale.get_supported_locales(None)],
+ "lang_link" : self.lang_link,
+ "link" : self.link,
+ "title" : "no title given",
+ "server" : self.request.host.replace("ipfire", "<span>ipfire</span>"),
+ "uri" : self.request.uri,
+ "year" : time.strftime("%Y"),
+ }
+
+ def render(self, *args, **kwargs):
+ nargs = self.render_args
+ nargs.update(kwargs)
+ nargs["title"] = "%s - %s" % (self.request.host, nargs["title"])
+ tornado.web.RequestHandler.render(self, *args, **nargs)
+
+ def link(self, s):
+ return "/%s/%s" % (self.locale.code[:2], s)
+
+ def lang_link(self, lang):
+ return "/%s/%s" % (lang, self.request.uri[4:])
+
+ def get_error_html(self, status_code, **kwargs):
+ if status_code in (404, 500):
+ render_args = self.render_args
+ render_args.update({
+ "code" : status_code,
+ "exception" : kwargs.get("exception", None),
+ "message" : httplib.responses[status_code],
+ })
+ return self.render_string("error-%s.html" % status_code, **render_args)
+ else:
+ return tornado.web.RequestHandler.get_error_html(self, status_code, **kwargs)
+
+ @property
+ def hash_db(self):
+ return self.application.hash_db
+
+class MainHandler(BaseHandler):
+ def get(self):
+ lang = self.locale.code[:2]
+ self.redirect("/%s/index" % (lang))
+
+
+class DownloadHandler(BaseHandler):
+ def get(self):
+ self.render("downloads.html", release=releases.latest)
+
+
+class DownloadAllHandler(BaseHandler):
+ def get(self):
+ self.render("downloads-all.html", releases=releases)
+
+
+class DownloadDevelopmentHandler(BaseHandler):
+ def get(self):
+ self.render("downloads-development.html", releases=releases)
+
+
+class DownloadTorrentHandler(BaseHandler):
+ tracker_url = "http://tracker.ipfire.org:6969/stats?format=txt&mode=tpbs"
+
+ @tornado.web.asynchronous
+ def get(self):
+ http = tornado.httpclient.AsyncHTTPClient()
+ http.fetch(self.tracker_url, callback=self.async_callback(self.on_response))
+
+ def on_response(self, response):
+ torrents = releases.torrents
+ hashes = {}
+ if response.code == 200:
+ for line in response.body.split("\n"):
+ if not line: continue
+ hash, seeds, peers = line.split(":")
+ hash.lower()
+ hashes[hash] = {
+ "peers" : peers,
+ "seeds" : seeds,
+ }
+
+ self.render("downloads-torrents.html",
+ hashes=hashes,
+ releases=torrents,
+ request_time=response.request_time,
+ tracker=urlparse.urlparse(response.request.url).netloc)
+
+
+class DownloadMirrorHandler(BaseHandler):
+ def get(self):
+ self.render("downloads-mirrors.html", mirrors=mirrors)
+
+
+class StaticHandler(BaseHandler):
+ @property
+ def static_path(self):
+ return os.path.join(self.application.settings["template_path"], "static")
+
+ @property
+ def static_files(self):
+ ret = []
+ for filename in os.listdir(self.static_path):
+ if filename.endswith(".html"):
+ ret.append(filename)
+ return ret
+
+ def get(self, name=None):
+ name = "%s.html" % name
+
+ if not name in self.static_files:
+ raise tornado.web.HTTPError(404)
+
+ self.render("static/%s" % name)
+
+
+class IndexHandler(BaseHandler):
+ def get(self):
+ self.render("index.html", news=news)
+
+
+class NewsHandler(BaseHandler):
+ def get(self):
+ self.render("news.html", news=news)
+
+
+class BuildHandler(BaseHandler):
+ def prepare(self):
+ self.builds = {
+ "<12h" : [],
+ ">12h" : [],
+ ">24h" : [],
+ }
+
+ for build in builds.find():
+ if (time.time() - float(build.get("date"))) < 12*60*60:
+ self.builds["<12h"].append(build)
+ elif (time.time() - float(build.get("date"))) < 24*60*60:
+ self.builds[">12h"].append(build)
+ else:
+ self.builds[">24h"].append(build)
+
+ for l in self.builds.values():
+ l.sort()
+
+ def get(self):
+ self.render("builds.html", builds=self.builds)
+
+
+class UrielBaseHandler(BaseHandler):
+ #db = uriel.Database()
+ pass
+
+class UrielHandler(UrielBaseHandler):
+ def get(self):
+ pass
+
+
+class ApiClusterInfoHandler(BaseHandler):
+ def get(self):
+ id = self.get_argument("id", "null")
+
+ c = cluster.Cluster(info["cluster"]["hostname"])
+
+ self.write(simplejson.dumps({
+ "version": "1.1",
+ "id": id,
+ "result" : c.json,
+ "error" : "null", }))
+ self.finish()
+
+
+class TranslationHandler(BaseHandler):
+ def get(self):
+ self.render("translations.html", projects=translations.projects)
+
+
+class SourceHandler(BaseHandler):
+ def get(self):
+ source_path = "/srv/sources"
+ fileobjects = []
+
+ for dir, subdirs, files in os.walk(source_path):
+ if not files:
+ continue
+ for file in files:
+ if file in [f["name"] for f in fileobjects]:
+ continue
+
+ hash = self.hash_db.get_hash(file)
+
+ if not hash:
+ hash = "0000000000000000000000000000000000000000"
+
+ fileobjects.append({
+ "dir" : dir[len(source_path)+1:],
+ "name" : file,
+ "hash" : hash,
+ "size" : size(os.path.getsize(os.path.join(source_path, dir, file))),
+ })
+
+ fileobjects.sort(key=operator.itemgetter("name"))
+
+ self.render("sources.html", files=fileobjects)
+
+
+class SourceDownloadHandler(BaseHandler):
+ def head(self, path):
+ self.get(path, include_body=False)
+
+ def get(self, path, include_body=True):
+ source_path = "/srv/sources"
+
+ path = os.path.abspath(os.path.join(source_path, path[1:]))
+
+ if not path.startswith(source_path):
+ raise tornado.web.HTTPError(403)
+ if not os.path.exists(path):
+ raise tornado.web.HTTPError(404)
+
+ stat_result = os.stat(path)
+ modified = datetime.datetime.fromtimestamp(stat_result[stat.ST_MTIME])
+
+ self.set_header("Last-Modified", modified)
+ self.set_header("Content-Length", stat_result[stat.ST_SIZE])
+
+ mime_type, encoding = mimetypes.guess_type(path)
+ if mime_type:
+ self.set_header("Content-Type", mime_type)
+
+ hash = self.hash_db.get_hash(path)
+ if hash:
+ self.set_header("X-Hash-Sha1", "%s" % hash)
+
+ if not include_body:
+ return
+ file = open(path, "r")
+ try:
+ self.write(file.read())
+ finally:
+ file.close()
+
+
+class DownloadFileHandler(BaseHandler):
+ def get(self, path):
+ for mirror in mirrors.with_file(path):
+ if not mirror.reachable:
+ continue
+
+ self.redirect(mirror.url + path)
+ return
+
+ raise tornado.web.HTTPError(404)
+
+ def get_error_html(self, status_code, **kwargs):
+ return tornado.web.RequestHandler.get_error_html(self, status_code, **kwargs)
--- /dev/null
+#!/usr/bin/python
+
+import simplejson
+import subprocess
+
+class Item(object):
+ def __init__(self, **args):
+ self.args = args
+
+ def __getattr__(self, key):
+ return self.args[key]
+
+ def __getitem__(self, key):
+ return self.args[key]
+
+ def __setitem__(self, key, val):
+ self.args[key] = val
+
+def size(s):
+ suffixes = ["B", "K", "M", "G", "T",]
+
+ idx = 0
+ while s >= 1024 and idx < len(suffixes):
+ s /= 1024
+ idx += 1
+
+ return "%.0f%s" % (s, suffixes[idx])
+
+def json_loads(s):
+ return simplejson.loads(s.decode("utf-8"))
+
+def _stringify(d):
+ ret = {}
+ for key in d.keys():
+ ret[str(key)] = d[key]
+ return ret
+
+def ping(host, count=5, wait=10):
+ cmd = subprocess.Popen(
+ ["ping", "-c%d" % count, "-w%d" % wait, host],
+ stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE,
+ )
+
+ latency = None
+
+ out, error = cmd.communicate()
+
+ for line in out.split("\n"):
+ if not line.startswith("rtt"):
+ continue
+
+ line = line.split()
+ if len(line) < 4:
+ break
+
+ rtts = line[3].split("/")
+ if len(rtts) < 4:
+ break
+
+ latency = "%.1f" % float(rtts[1])
+
+ return latency
+
+
+if __name__ == "__main__":
+ print ping("www.ipfire.org")
+ print ping("www.rowie.at")
--- /dev/null
+#!/usr/bin/python
+
+from helpers import json_loads
+
+class Info(dict):
+ def __init__(self, filename):
+ self.load(filename)
+
+ def load(self, filename):
+ f = open(filename)
+ for key, val in json_loads(f.read()).items():
+ self[key] = val
+ f.close()
+
+
+info = Info("info.json")
--- /dev/null
+#!/usr/bin/python
+
+import simplejson
+
+from helpers import Item, _stringify
+
+class Menu(object):
+ def __init__(self, filename=None):
+ self.items = []
+
+ if filename:
+ self.load(filename)
+
+ def load(self, filename):
+ f = open(filename)
+ data = f.read()
+ f.close()
+
+ for item in simplejson.loads(data):
+ self.items.append(MenuItem(**_stringify(item)))
+
+
+class MenuItem(Item):
+ def __init__(self, **args):
+ Item.__init__(self, **args)
+ self.active = False
+
+ # Parse submenu
+ if self.args.has_key("subs"):
+ self.args["items"] = []
+ for sub in self.args["subs"]:
+ self.args["items"].append(MenuItem(**_stringify(sub)))
+ del self.args["subs"]
+
+
+if __name__ == "__main__":
+ m = Menu("menu.json")
+ print [i.args for i in m.items]
--- /dev/null
+#!/usr/bin/python
+
+import tornado.httpclient
+
+import random
+import threading
+import time
+
+from helpers import Item, _stringify, ping, json_loads
+
+class Mirrors(threading.Thread):
+ def __init__(self, filename):
+ threading.Thread.__init__(self, name="Mirror Monitor")
+
+ self.items = []
+ self.load(filename)
+
+ self.__running = True
+
+ self.start()
+
+ def load(self, filename):
+ f = open(filename)
+ data = f.read()
+ f.close()
+
+ for item in json_loads(data):
+ self.items.append(MirrorItem(**_stringify(item)))
+
+ @property
+ def all(self):
+ return sorted(self.items)
+
+ @property
+ def random(self):
+ # Doesnt work :(
+ #return random.shuffle(self.items)
+ ret = []
+ items = self.items[:]
+ while items:
+ rnd = random.randint(0, len(items)-1)
+ ret.append(items.pop(rnd))
+ return ret
+
+ @property
+ def reachable(self):
+ ret = []
+ for mirror in self.items:
+ if not mirror.reachable:
+ continue
+ ret.append(mirror)
+ return ret
+
+ @property
+ def unreachable(self):
+ ret = []
+ for mirror in self.all:
+ if mirror in self.reachable:
+ continue
+ ret.append(mirror)
+ return ret
+
+ def pickone(self, reachable=False):
+ mirrors = self.items
+ if reachable:
+ mirrors = self.reachable
+ if not mirrors:
+ return None
+ return random.choice(mirrors)
+
+ def with_file(self, path):
+ ret = []
+ for mirror in self.random:
+ if not mirror["serves"]["isos"]:
+ continue
+ if path in mirror.files:
+ ret.append(mirror)
+ return ret
+
+ def shutdown(self):
+ self.__running = False
+
+ def run(self):
+ for mirror in self.random:
+ if not self.__running:
+ return
+ mirror.update()
+
+ count = 0
+ while self.__running:
+ if not count:
+ count = 300 # 30 secs
+ mirror = self.pickone()
+ if mirror:
+ mirror.update()
+
+ time.sleep(0.1)
+ count -= 1
+
+
+class MirrorItem(Item):
+ def __init__(self, *args, **kwargs):
+ Item.__init__(self, *args, **kwargs)
+
+ self.filelist = MirrorFilelist(self)
+ self.latency = "N/A"
+
+ def __cmp__(self, other):
+ return cmp(self.name, other.name)
+
+ def update(self):
+ self.latency = ping(self.hostname) or "N/A"
+ if self.filelist.outdated:
+ self.filelist.update()
+
+ @property
+ def reachable(self):
+ return not self.latency == "N/A"
+
+ @property
+ def url(self):
+ ret = "http://" + self.hostname
+ if not self.path.startswith("/"):
+ ret += "/"
+ ret += self.path
+ if not ret.endswith("/"):
+ ret += "/"
+ return ret
+
+ @property
+ def files(self):
+ return self.filelist.files
+
+ def has_file(self, path):
+ return path in self.files
+
+
+class MirrorFilelist(object):
+ def __init__(self, mirror):
+ self.mirror = mirror
+
+ self.__files = []
+ self.__time = 0
+
+ #self.update(now=True)
+
+ def update(self, now=False):
+ args = {}
+
+ if now:
+ while not self.mirror.reachable:
+ time.sleep(10)
+
+ http = tornado.httpclient.HTTPClient()
+
+ if not now:
+ http = tornado.httpclient.AsyncHTTPClient()
+ args["callback"] = self.on_response
+
+ try:
+ reponse = http.fetch(self.mirror.url + ".filelist", **args)
+ except tornado.httpclient.HTTPError:
+ self.__time = time.time()
+ return
+
+ if now:
+ self.on_response(reponse)
+
+ def on_response(self, response):
+ self.__files = []
+ self.__time = time.time()
+
+ if not response.code == 200:
+ return
+
+ # If invalid html content...
+ if response.body.startswith("<!"):
+ return
+
+ for line in response.body.split("\n"):
+ if not line:
+ continue
+ self.__files.append(line)
+
+ @property
+ def outdated(self):
+ return (time.time() - self.__time) > 60*60
+
+ @property
+ def files(self):
+ #if self.outdated:
+ # self.update()
+ return self.__files
+
+
+mirrors = Mirrors("mirrors.json")
--- /dev/null
+#!/usr/bin/python
+
+from helpers import Item, _stringify, json_loads
+
+class News(object):
+ def __init__(self, filename=None):
+ self.items = []
+
+ if filename:
+ self.load(filename)
+
+ def load(self, filename):
+ f = open(filename)
+ data = f.read()
+ f.close()
+
+ data = data.replace("\n", "").replace("\t", " ")
+
+ json = json_loads(data)
+ for key in sorted(json.keys()):
+ self.items.append(NewsItem(**_stringify(json[key])))
+
+ def get(self, limit=None):
+ ret = self.items[:]
+ ret.reverse()
+ if limit:
+ ret = ret[:limit]
+ return ret
+
+
+NewsItem = Item
+
+news = News("news.json")
--- /dev/null
+#!/usr/bin/python
+
+from helpers import Item, _stringify, json_loads
+
+class ReleaseItem(Item):
+ options = {
+ "iso" : {
+ "prio" : 10,
+ "desc" : "Installable CD image",
+ "url" : "http://download.ipfire.org/iso/",
+ "rem" : "Use this image to burn a CD and install IPFire from it.",
+ },
+ "torrent" : {
+ "prio" : 20,
+ "desc" : "Torrent file",
+ "url" : "http://download.ipfire.org/torrent/",
+ "rem" : "Download the CD image from the torrent network.",
+ },
+ "flash" : {
+ "prio" : 40,
+ "desc" : "Flash image",
+ "url" : "http://download.ipfire.org/iso/",
+ "rem" : "An image that is meant to run on embedded devices.",
+ },
+ "alix" : {
+ "prio" : 41,
+ "desc" : "Alix image",
+ "url" : "http://download.ipfire.org/iso/",
+ "rem" : "Flash image where a serial console is enabled by default.",
+ },
+ "usbfdd" : {
+ "prio" : 30,
+ "desc" : "USB FDD image",
+ "url" : "http://download.ipfire.org/iso/",
+ "rem" : "Install IPFire from a floppy-formated USB key.",
+ },
+ "usbhdd" : {
+ "prio" : 30,
+ "desc" : "USB HDD image",
+ "url" : "http://download.ipfire.org/iso/",
+ "rem" : "If the floppy image doesn't work, use this image instead.",
+ },
+ "xen" : {
+ "prio" : 50,
+ "desc" : "Pregenerated Xen image",
+ "url" : "http://download.ipfire.org/iso/",
+ "rem" : "A ready-to-run image for Xen.",
+ },
+ }
+
+ @property
+ def downloads(self):
+ ret = []
+ for fileitem in self.args["files"]:
+ filetype = fileitem["type"]
+ ret.append(Item(
+ desc = self.options[filetype]["desc"],
+ file = fileitem["name"],
+ hash = fileitem.get("hash", None),
+ prio = self.options[filetype]["prio"],
+ rem = self.options[filetype]["rem"],
+ sha1 = fileitem.get("sha1", None),
+ type = filetype,
+ url = self.options[filetype]["url"] + fileitem["name"],
+ ))
+
+ ret.sort(lambda a, b: cmp(a.prio, b.prio))
+ return ret
+
+ for option in self.options.keys():
+ if not self.args["files"].has_key(option):
+ continue
+
+ ret.append(Item(
+ desc = self.options[option]["desc"],
+ file = self.args["files"][option],
+ prio = self.options[option]["prio"],
+ type = option,
+ url = self.options[option]["url"] + self.args["files"][option],
+ ))
+
+ ret.sort(lambda a, b: cmp(a.prio, b.prio))
+ return ret
+
+ @property
+ def iso(self):
+ for download in self.downloads:
+ if download.type == "iso":
+ return download
+
+ @property
+ def torrent(self):
+ for download in self.downloads:
+ if download.type == "torrent":
+ return download
+
+ @property
+ def stable(self):
+ return self.status == "stable"
+
+ @property
+ def development(self):
+ return self.status == "development"
+
+
+class Releases(object):
+ def __init__(self, filename="releases.json"):
+ self.items = []
+
+ if filename:
+ self.load(filename)
+
+ def load(self, filename):
+ f = open(filename)
+ data = f.read()
+ f.close()
+
+ for item in json_loads(data):
+ self.items.append(ReleaseItem(**_stringify(item)))
+
+ @property
+ def all(self):
+ return self.items
+
+ @property
+ def online(self):
+ ret = []
+ for item in self.all:
+ if item.online:
+ ret.append(item)
+ return ret
+
+ @property
+ def offline(self):
+ ret = []
+ for item in self.all:
+ if not item.online:
+ ret.append(item)
+ return ret
+
+ @property
+ def latest(self):
+ if self.stable:
+ return self.stable[0]
+
+ @property
+ def latest_devel(self):
+ if self.development:
+ return self.development[0]
+
+ @property
+ def stable(self):
+ ret = []
+ for item in self.online:
+ if item.stable:
+ ret.append(item)
+ return ret
+
+ @property
+ def development(self):
+ ret = []
+ for item in self.online:
+ if item.development:
+ ret.append(item)
+ return ret
+
+ @property
+ def torrents(self):
+ ret = []
+ for item in self.online:
+ if item.torrent:
+ ret.append(item)
+ return ret
+
+
+releases = Releases("releases.json")
+
+if __name__ == "__main__":
+ r = Releases()
+
+ print r.stable
+ print r.development
+ print r.latest
+ print r.online
+ print r.offline
--- /dev/null
+#!/usr/bin/python
+
+import os
+
+import tornado.locale
+
+class Po(object):
+ def __init__(self, path, project):
+ self.path = path
+ self.project = project
+
+ p = os.popen("msgfmt -v --statistics %s 2>&1" % self.path)
+ self.line = p.readlines()[0]
+
+ def __cmp__(self, other):
+ return cmp(self.lang, other.lang)
+
+ @property
+ def code2lang(self):
+ ret = {}
+ for lang in tornado.locale.LOCALE_NAMES.keys():
+ ret[lang[:2]] = "%(name)s (%(name_en)s)" % tornado.locale.LOCALE_NAMES[lang]
+ return ret
+
+ @property
+ def code(self):
+ return os.path.basename(self.path)[:-3]
+
+ @property
+ def lang(self):
+ return self.code2lang.get(self.code, "Unknown (%s)" % self.code)
+
+ @property
+ def translated(self):
+ return int(self.line.split()[0])
+
+ @property
+ def untranslated(self):
+ l = self.line.split()
+ if len(l) == 6:
+ return int(l[3])
+ elif len(l) == 9:
+ return int(l[6])
+ return 0
+
+ @property
+ def fuzzy(self):
+ l = self.line.split()
+ if len(l) == 9:
+ return l[3]
+ return 0
+
+ @property
+ def percent(self):
+ if not self.project.total_strings:
+ return "---.-- %"
+
+ return "%3.1f%%" % (self.translated * 100 / self.project.total_strings)
+
+
+class Project(object):
+ def __init__(self, id, path, **kwargs):
+ self.id = id
+ self.path = path
+ self._name = kwargs.pop("name")
+ self.desc = kwargs.pop("desc")
+
+ self._translations = []
+ self.pot = None
+ self.find_pot()
+
+ @property
+ def name(self):
+ if self._name:
+ return self._name
+ return self.id
+
+ @property
+ def translations(self):
+ if not self._translations:
+ for path in os.listdir(self.path):
+ if path.endswith(".po"):
+ self._translations.append(Po(os.path.join(self.path, path), self))
+ self._translations.sort()
+ return self._translations
+
+ def find_pot(self):
+ for path in os.listdir(self.path):
+ if path.endswith(".pot"):
+ self.pot = Po(os.path.join(self.path, path), self)
+ break
+
+ @property
+ def total_strings(self):
+ if not self.pot:
+ return 0
+ return self.pot.untranslated
+
+projects = [
+ Project("pomona", "/srv/checkout/ipfire-3.x/src/pomona/po",
+ name="Pomona", desc="The pomona installer for ipfire."),
+]
--- /dev/null
+#!/usr/bin/python
+
+import tornado.web
+
+import menu
+import releases
+
+from helpers import Item
+
+class UIModule(tornado.web.UIModule):
+ def render_string(self, *args, **kwargs):
+ kwargs.update({
+ "link" : self.handler.link,
+ })
+ return tornado.web.UIModule.render_string(self, *args, **kwargs)
+
+
+class MenuItemModule(UIModule):
+ def render(self, item):
+ if self.request.uri.endswith(item.uri):
+ item.active = True
+
+ if not item.uri.startswith("http://"):
+ item.uri = "/%s%s" % (self.locale.code[:2], item.uri,)
+
+ if type(item.name) == type({}):
+ item.name = item.name[self.locale.code[:2]]
+
+ return self.render_string("modules/menu-item.html", item=item)
+
+
+class MenuModule(UIModule):
+ def render(self, menuclass=None):
+ if not menuclass:
+ menuclass = menu.Menu("menu.json")
+ return self.render_string("modules/menu.html", menuitems=menuclass.items)
+
+
+class NewsItemModule(UIModule):
+ def render(self, item):
+ item = Item(**item.args.copy())
+ for attr in ("subject", "content"):
+ if type(item[attr]) != type({}):
+ continue
+ item[attr] = item[attr][self.locale.code[:2]]
+
+ return self.render_string("modules/news-item.html", item=item)
+
+
+#class SidebarModule(UIModule):
+# def render(self, sidebar):
+# return self.render_string("modules/sidebar.html", items=sidebar.items)
+
+
+class SidebarItemModule(UIModule):
+ def render(self):
+ return self.render_string("modules/sidebar-item.html")
+
+
+class SidebarReleaseModule(UIModule):
+ releases = releases.Releases()
+
+ def render(self):
+ return self.render_string("modules/sidebar-release.html",
+ releases=self.releases)
+
+
+class ReleaseItemModule(UIModule):
+ def render(self, item):
+ return self.render_string("modules/release-item.html", item=item)
+
+
+class SidebarBannerModule(UIModule):
+ def render(self, item):
+ return self.render_string("modules/sidebar-banner.html", item=item)
+
+
+class BuildModule(UIModule):
+ def render(self, build):
+ return self.render_string("modules/builds.html", build=build)
allowed_items = [ "cpu_mhz", "cpu_model", "formfactor", "lang", "model",
"ram_mb", "storage_mb", "system", "vendor", ]
-class Urieldb(object):
+class Database(object):
_name = "uriel"
_table = "hosts"