summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2012-11-15 01:12:12 -0500
committerLuke Shumaker <LukeShu@sbcglobal.net>2012-11-15 01:12:12 -0500
commit38f1b73179154c1fef676021acd6362e88837a89 (patch)
tree14b7789ccb23a7d0715dc9cfc75d3de0d3700dcf
parentaa2836cb3859e05e9524def5ec37706e3299205c (diff)
parent03a0d27971898592698dbb0c5948b93c6a3a4741 (diff)
Merge tag 'release_2012-02-18'
Defend against bogus URLs, mirrorlist no FTP by default Conflicts: templates/public/index.html
-rw-r--r--devel/views.py10
-rw-r--r--mirrors/admin.py8
-rw-r--r--mirrors/fixtures/mirrorprotocols.json5
-rw-r--r--mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py66
-rw-r--r--mirrors/migrations/0011_adjust_protocol_defaults.py67
-rw-r--r--mirrors/models.py2
-rw-r--r--mirrors/views.py6
-rw-r--r--packages/templatetags/package_extras.py7
-rw-r--r--packages/urls.py2
-rw-r--r--packages/views/__init__.py2
-rw-r--r--packages/views/flag.py6
-rw-r--r--templates/public/index.html45
12 files changed, 187 insertions, 39 deletions
diff --git a/devel/views.py b/devel/views.py
index dc2283ca..793d1520 100644
--- a/devel/views.py
+++ b/devel/views.py
@@ -209,8 +209,10 @@ def report(request, report_name, username=None):
elif report_name == 'uncompressed-man':
title = 'Packages with uncompressed manpages'
# checking for all '.0'...'.9' + '.n' extensions
- bad_files = PackageFile.objects.filter(directory__contains='/man/',
- filename__regex=r'\.[0-9n]').exclude(filename__endswith='.gz')
+ bad_files = PackageFile.objects.filter(is_directory=False,
+ directory__contains='/man/',
+ filename__regex=r'\.[0-9n]').exclude(
+ filename__endswith='.gz').exclude(filename__endswith='.html')
if username:
pkg_ids = set(packages.values_list('id', flat=True))
bad_files = bad_files.filter(pkg__in=pkg_ids)
@@ -220,8 +222,8 @@ def report(request, report_name, username=None):
title = 'Packages with uncompressed infopages'
# we don't worry about looking for '*.info-1', etc., given that an
# uncompressed root page probably exists in the package anyway
- bad_files = PackageFile.objects.filter(directory__endswith='/info/',
- filename__endswith='.info')
+ bad_files = PackageFile.objects.filter(is_directory=False,
+ directory__endswith='/info/', filename__endswith='.info')
if username:
pkg_ids = set(packages.values_list('id', flat=True))
bad_files = bad_files.filter(pkg__in=pkg_ids)
diff --git a/mirrors/admin.py b/mirrors/admin.py
index 3786d8d2..a2b59b41 100644
--- a/mirrors/admin.py
+++ b/mirrors/admin.py
@@ -56,7 +56,9 @@ class MirrorRsyncInlineAdmin(admin.TabularInline):
class MirrorAdminForm(forms.ModelForm):
class Meta:
model = Mirror
- upstream = forms.ModelChoiceField(queryset=Mirror.objects.filter(tier__gte=0, tier__lte=1), required=False)
+ upstream = forms.ModelChoiceField(
+ queryset=Mirror.objects.filter(tier__gte=0, tier__lte=1),
+ required=False)
class MirrorAdmin(admin.ModelAdmin):
form = MirrorAdminForm
@@ -70,8 +72,8 @@ class MirrorAdmin(admin.ModelAdmin):
]
class MirrorProtocolAdmin(admin.ModelAdmin):
- list_display = ('protocol', 'is_download',)
- list_filter = ('is_download',)
+ list_display = ('protocol', 'is_download', 'default')
+ list_filter = ('is_download', 'default')
admin.site.register(Mirror, MirrorAdmin)
admin.site.register(MirrorProtocol, MirrorProtocolAdmin)
diff --git a/mirrors/fixtures/mirrorprotocols.json b/mirrors/fixtures/mirrorprotocols.json
index 35614b3a..72ed1a7f 100644
--- a/mirrors/fixtures/mirrorprotocols.json
+++ b/mirrors/fixtures/mirrorprotocols.json
@@ -4,6 +4,7 @@
"model": "mirrors.mirrorprotocol",
"fields": {
"is_download": true,
+ "default": true,
"protocol": "http"
}
},
@@ -12,6 +13,7 @@
"model": "mirrors.mirrorprotocol",
"fields": {
"is_download": true,
+ "default": false,
"protocol": "ftp"
}
},
@@ -20,7 +22,8 @@
"model": "mirrors.mirrorprotocol",
"fields": {
"is_download": false,
+ "default": false,
"protocol": "rsync"
}
}
-] \ No newline at end of file
+]
diff --git a/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py b/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py
new file mode 100644
index 00000000..6868cb25
--- /dev/null
+++ b/mirrors/migrations/0010_auto__add_field_mirrorprotocol_default.py
@@ -0,0 +1,66 @@
+# encoding: utf-8
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ db.add_column('mirrors_mirrorprotocol', 'default', self.gf('django.db.models.fields.BooleanField')(default=True), keep_default=False)
+
+ def backwards(self, orm):
+ db.delete_column('mirrors_mirrorprotocol', 'default')
+
+
+ models = {
+ 'mirrors.mirror': {
+ 'Meta': {'ordering': "('country', 'name')", 'object_name': 'Mirror'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True'})
+ },
+ 'mirrors.mirrorlog': {
+ 'Meta': {'object_name': 'MirrorLog'},
+ 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"})
+ },
+ 'mirrors.mirrorprotocol': {
+ 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'},
+ 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'mirrors.mirrorrsync': {
+ 'Meta': {'object_name': 'MirrorRsync'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"})
+ },
+ 'mirrors.mirrorurl': {
+ 'Meta': {'object_name': 'MirrorUrl'},
+ 'country': ('mirrors.models.NullCharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ }
+ }
+
+ complete_apps = ['mirrors']
diff --git a/mirrors/migrations/0011_adjust_protocol_defaults.py b/mirrors/migrations/0011_adjust_protocol_defaults.py
new file mode 100644
index 00000000..0118de67
--- /dev/null
+++ b/mirrors/migrations/0011_adjust_protocol_defaults.py
@@ -0,0 +1,67 @@
+# encoding: utf-8
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ orm.MirrorProtocol.objects.all().update(default=False)
+ orm.MirrorProtocol.objects.filter(protocol='http').update(default=True)
+
+ def backwards(self, orm):
+ pass
+
+
+ models = {
+ 'mirrors.mirror': {
+ 'Meta': {'ordering': "('country', 'name')", 'object_name': 'Mirror'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}),
+ 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True'})
+ },
+ 'mirrors.mirrorlog': {
+ 'Meta': {'object_name': 'MirrorLog'},
+ 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"})
+ },
+ 'mirrors.mirrorprotocol': {
+ 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'},
+ 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'mirrors.mirrorrsync': {
+ 'Meta': {'object_name': 'MirrorRsync'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"})
+ },
+ 'mirrors.mirrorurl': {
+ 'Meta': {'object_name': 'MirrorUrl'},
+ 'country': ('mirrors.models.NullCharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ }
+ }
+
+ complete_apps = ['mirrors']
diff --git a/mirrors/models.py b/mirrors/models.py
index 111654fd..86905eea 100644
--- a/mirrors/models.py
+++ b/mirrors/models.py
@@ -54,6 +54,8 @@ class MirrorProtocol(models.Model):
protocol = models.CharField(max_length=10, unique=True)
is_download = models.BooleanField(default=True,
help_text="Is protocol useful for end-users, e.g. FTP/HTTP")
+ default = models.BooleanField(default=True,
+ help_text="Included by default when building mirror list?")
def __unicode__(self):
return self.protocol
diff --git a/mirrors/views.py b/mirrors/views.py
index 417e26ee..2ef8654d 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -29,8 +29,9 @@ class MirrorlistForm(forms.Form):
self.fields['country'].initial = ['all']
protos = make_choice(
MirrorProtocol.objects.filter(is_download=True))
+ initial = MirrorProtocol.objects.filter(is_download=True, default=True)
self.fields['protocol'].choices = protos
- self.fields['protocol'].initial = [t[0] for t in protos]
+ self.fields['protocol'].initial = [p.protocol for p in initial]
self.fields['ip_version'].initial = ['4']
@csrf_exempt
@@ -48,7 +49,8 @@ def generate_mirrorlist(request):
else:
form = MirrorlistForm()
- return direct_to_template(request, 'mirrors/index.html', {'mirrorlist_form': form})
+ return direct_to_template(request, 'mirrors/index.html',
+ {'mirrorlist_form': form})
def find_mirrors(request, countries=None, protocols=None, use_status=False,
ipv4_supported=True, ipv6_supported=True):
diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py
index 71ff5ed8..2e68ef0c 100644
--- a/packages/templatetags/package_extras.py
+++ b/packages/templatetags/package_extras.py
@@ -9,8 +9,11 @@ from django.utils.html import escape
register = template.Library()
-def link_encode(url, query, doseq=False):
- data = urlencode(query, doseq).replace('&', '&amp;')
+def link_encode(url, query):
+ # massage the data into all utf-8 encoded strings first, so urlencode
+ # doesn't barf at the data we pass it
+ query = dict((k, unicode(v).encode('utf-8')) for k, v in query.items())
+ data = urlencode(query).replace('&', '&amp;')
return "%s?%s" % (url, data)
@register.filter
diff --git a/packages/urls.py b/packages/urls.py
index 6c616297..52b09d2c 100644
--- a/packages/urls.py
+++ b/packages/urls.py
@@ -28,7 +28,7 @@ urlpatterns = patterns('packages.views',
(r'^stale_relations/$', 'stale_relations'),
(r'^stale_relations/update/$','stale_relations_update'),
- (r'^(?P<name>[A-z0-9\-+.]+)/$',
+ (r'^(?P<name>[^ /]+)/$',
'details'),
(r'^(?P<repo>[A-z0-9\-]+)/(?P<name>[^ /]+)/$',
'details'),
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 9ca21407..08e0286c 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -142,7 +142,7 @@ def details(request, name='', repo='', arch=''):
('q', name),
]
# only include non-blank values in the query we generate
- pkg_data = [(x, y) for x, y in pkg_data if y]
+ pkg_data = [(x, y.encode('utf-8')) for x, y in pkg_data if y]
return redirect("/packages/?%s" % urlencode(pkg_data))
def groups(request, arch=None):
diff --git a/packages/views/flag.py b/packages/views/flag.py
index ad1b04db..e87cef69 100644
--- a/packages/views/flag.py
+++ b/packages/views/flag.py
@@ -18,9 +18,9 @@ def flaghelp(request):
return direct_to_template(request, 'packages/flaghelp.html')
class FlagForm(forms.Form):
- email = forms.EmailField(label='* E-mail Address')
- message = forms.CharField(label='Message To Dev',
- widget=forms.Textarea, required=False)
+ email = forms.EmailField(label='E-mail Address')
+ message = forms.CharField(label='Message To Developer',
+ widget=forms.Textarea)
# The field below is used to filter out bots that blindly fill out all
# input elements
website = forms.CharField(label='',
diff --git a/templates/public/index.html b/templates/public/index.html
index 0d57e505..15db0719 100644
--- a/templates/public/index.html
+++ b/templates/public/index.html
@@ -25,7 +25,7 @@
<p>You can find us on IRC at <a
href="irc://irc.freenode.net/#parabola">irc.freenode.net/#parabola</a>.</p>
-
+
<p class="readmore"><a href="{% url page-about %}"
title="Learn more about Parabola">Learn more...</a></p>
@@ -39,7 +39,7 @@
</h3>
<a href="/feeds/news/" title="Parabola News RSS Feed"
- class="rss-icon"><img src="{{ STATIC_URL }}rss.png" alt="RSS Feed" /></a>
+ class="rss-icon"><img src="{% cdnprefix %}/media/rss.png" alt="RSS Feed" /></a>
{% for news in news_updates %}
{% if forloop.counter0 < 5 %}
@@ -92,7 +92,7 @@
title="Browse all of the latest packages">more</a>)</span></h3>
<a href="/feeds/packages/" title="Parabola Package Updates RSS Feed"
- class="rss-icon"><img src="{{ STATIC_URL }}rss.png" alt="RSS Feed" /></a>
+ class="rss-icon"><img src="{% cdnprefix %}/media/rss.png" alt="RSS Feed" /></a>
<table>
{% for update in pkg_updates %}
@@ -153,38 +153,31 @@
<h4>Development</h4>
<ul>
- <li><a href="{% url page-keys %}"
- title="Package/Database signing master keys">Master Keys</a>
- <img src="{% cdnprefix %}/media/new.png" alt="New"/></li>
- <li><a href="/packages/"
- title="View/search the package repository database">Packages</a></li>
- <li><a href="/groups/"
- title="View the available package groups">Package Groups</a></li>
- <li><a href="{% url visualize-index %}"
- title="View visualizations">Visualizations</a>
- <img src="{% cdnprefix %}/media/new.png" alt="New"/></li>
-{% comment %}
- <li><a href="{% url page-svn %}"
- title="View SVN entries for packages">SVN Repositories</a></li>
-{% endcomment %}
<li><a href="https://projects.parabolagnulinux.org"
title="Official Parabola projects (git)">Projects in Git</a></li>
{% comment %}
+ <li><a href="{% url page-svn %}"
+ title="View SVN entries for packages">SVN Repositories</a></li>
<li><a href="https://wiki.archlinux.org/index.php/DeveloperWiki"
- title="Developer Wiki articles">DeveloperWiki</a></li>
+ title="Developer Wiki articles">Developer Wiki</a></li>
{% endcomment %}
+ <li><a href="/groups/"
+ title="View the available package groups">Package Groups</a></li>
<li><a href="/todolists/"
title="Hacker Todo Lists">Todo Lists</a></li>
<li><a href="{% url releng-test-overview %}"
title="Releng Testbuild Feedback">Releng Testbuild Feedback</a></li>
+ <li><a href="{% url visualize-index %}"
+ title="View visualizations">Visualizations</a>
+ <img src="{% cdnprefix %}/media/new.png" alt="New"/></li>
</ul>
- <h4>About</h4>
+ <h4>More Resources</h4>
<ul>
- <li><a href="{% url page-about %}"
- title="Learn more about Parabola">About Parabola</a></li>
- <li><a href="/download/" title="Get Parabola">Download Parabola</a></li>
+ <li><a href="{% url page-keys %}"
+ title="Package/Database signing master keys">Signing Master Keys</a>
+ <img src="{% cdnprefix %}/media/new.png" alt="New"/></li>
<li><a href="https://wiki.parabolagnulinux.org/Media"
title="Parabola in the media">Media Appearances</a></li>
<li><a href="{% url page-art %}" title="Parabola logos and other artwork for promotional use">Logos &amp; Artwork</a></li>
@@ -196,7 +189,14 @@
</div><!-- #nav-sidebar -->
+{% comment %}
+<div id="home-donate-button" class="widget">
+donate button would go here
+</div>
+{% endcomment %}
+
<div id="arch-sponsors" class="widget">
+
<a href="http://gnuchile.org">
<img src="{{ STATIC_URL }}gnuchile.png"
alt="GNU Chile - Donates the .org domain"
@@ -218,6 +218,7 @@
alt="Freedom Included - Donated Lemote Yeeloongs to port Parabola to the MIPS architecture"
title="Freedom Included - Donated Lemote Yeeloongs to port Parabola to the MIPS architecture" />
</a>
+
</div>
{% endcache %}
{% endblock %}