summaryrefslogtreecommitdiff
path: root/libre
diff options
context:
space:
mode:
authorMárcio Alexandre Silva Delgado <coadde@lavabit.com>2012-10-21 19:51:39 -0200
committerMárcio Alexandre Silva Delgado <coadde@lavabit.com>2012-10-21 19:51:39 -0200
commitee7f9096475e0ea57d9326d087f94e3df4c6512b (patch)
tree0e9b42a4cb590b3c59632a91b519e0bacac38bd3 /libre
parentb4ce63a23bfc79192dfc546c4196ec651dd31393 (diff)
parentb09b1d60e80ef66c0817fcc7466a20ec5a365520 (diff)
downloadabslibre-ee7f9096475e0ea57d9326d087f94e3df4c6512b.tar.gz
abslibre-ee7f9096475e0ea57d9326d087f94e3df4c6512b.tar.bz2
abslibre-ee7f9096475e0ea57d9326d087f94e3df4c6512b.zip
Merge branch 'master' of ssh://parabolagnulinux.org:1863/srv/git/abslibre
Diffstat (limited to 'libre')
-rwxr-xr-xlibre/apache-ant/PKGBUILD110
-rwxr-xr-xlibre/apache-ant/apache-ant.csh2
-rwxr-xr-xlibre/apache-ant/apache-ant.sh2
-rw-r--r--libre/django13/PKGBUILD47
-rw-r--r--libre/django13/PKGBUILD.orig40
-rw-r--r--libre/django13/diff-django_branches_releases_1.3.X-from-16768-to-17460.diff1573
-rw-r--r--libre/django13/diff-django_branches_releases_1.3.X-from-16771-to-17460.diff1575
-rwxr-xr-xlibre/java-asm2/PKGBUILD76
-rwxr-xr-xlibre/java-asm3/PKGBUILD78
-rwxr-xr-xlibre/java-ow-util-ant-tasks/PKGBUILD27
-rwxr-xr-xlibre/java-ow-util-ant-tasks/SRCBUILD29
-rwxr-xr-xlibre/maven-libre/PKGBUILD76
-rwxr-xr-xlibre/maven-libre/maven.csh2
-rwxr-xr-xlibre/maven-libre/maven.sh3
-rwxr-xr-xlibre/parabolaweb-git/Makefile26
-rwxr-xr-xlibre/parabolaweb-git/PKGBUILD43
-rwxr-xr-xlibre/parabolaweb-git/deps-ver.txt7
-rwxr-xr-xlibre/parabolaweb-git/parabolaweb.init.sh52
-rwxr-xr-xlibre/parabolaweb-git/parabolaweb.update.sh.in59
-rwxr-xr-xlibre/parabolaweb-git/requirements_prod.txt7
-rw-r--r--libre/parabolaweb-utils/PKGBUILD46
-rw-r--r--libre/parabolaweb-utils/helper.sh39
-rw-r--r--libre/parabolaweb-utils/parabolaweb-fcgi12
-rw-r--r--libre/parabolaweb-utils/parabolaweb-update81
-rw-r--r--libre/parabolaweb-utils/parabolaweb.conf3
-rw-r--r--libre/parabolaweb-utils/parabolaweb.rc43
-rw-r--r--libre/parabolaweb-utils/parabolaweb.service10
-rw-r--r--libre/tp_smapi-libre-lts/PKGBUILD60
-rw-r--r--libre/tp_smapi-libre-lts/tp_smapi-lts.install13
-rw-r--r--libre/virtualbox-libre-modules-lts/PKGBUILD10
-rwxr-xr-xlibre/virtualbox-libre-modules/PKGBUILD4
-rw-r--r--libre/virtualbox-libre/001-vboxdrv-reference.patch (renamed from libre/virtualbox-libre/vboxdrv-reference.patch)0
-rwxr-xr-xlibre/virtualbox-libre/002-change_default_driver_dir.patch (renamed from libre/virtualbox-libre/change_default_driver_dir.patch)0
-rw-r--r--libre/virtualbox-libre/003-remove_qt_fa_IR.patch23
-rwxr-xr-xlibre/virtualbox-libre/PKGBUILD38
-rwxr-xr-xlibre/virtualbox-libre/gsoap.patch11
-rwxr-xr-xlibre/virtualbox-libre/ipv6_vnc.patch20
-rwxr-xr-xlibre/virtualbox-libre/libre.patch4907
-rwxr-xr-xlibre/virtualbox-libre/vboxbuild95
-rwxr-xr-xlibre/xulrunner-libre/Bug-756390-Make-the-Reset-Firefox-feature-more-gener.patch20
-rwxr-xr-xlibre/xulrunner-libre/PKGBUILD8
41 files changed, 3609 insertions, 5668 deletions
diff --git a/libre/apache-ant/PKGBUILD b/libre/apache-ant/PKGBUILD
deleted file mode 100755
index 77e0dfe94..000000000
--- a/libre/apache-ant/PKGBUILD
+++ /dev/null
@@ -1,110 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-# Maintainer (Arch): Paul Mattal <paul@archlinux.org>
-# Contributor: Andrew Wright <andreww@photism.org>
-
-pkgname=apache-ant
-pkgver=1.8.4
-
-provides=("apache-ant-libre=$pkgver")
-replaces=("apache-ant-libre")
-conflicts=("apache-ant-libre")
-
-pkgrel=1.1
-pkgdesc="A Java-based build tool"
-arch=('any')
-license=('Apache')
-url="http://ant.apache.org/"
-_mirror=http://archive.apache.org/dist
-source=($_mirror/ant/source/${pkgname}-${pkgver}-src.tar.bz2
- ${pkgname}.sh ${pkgname}.csh)
-depends=('java-environment')
-
-# This list is adapted from https://ant.apache.org/manual/install.html#librarydependencies
-declare -A _opts
-_opts[junit]='to have JUnit on the classpath in javac tasks;/usr/share/java/junit.jar'
-_opts[xalan-java]='<junitreport> task;/usr/share/java/xalan.jar'
-_opts[antlr2]='<antlr> task;/usr/share/java/antlr2.jar::antlr.jar'
-#_opts[java-bsf]='<script> task;/usr/share/java/bsf.jar'
-#_opts[groovy]='Groovy with <script> and <scriptdef> tasks;/usr/share/java/groovy.jar'
-_opts[java-asm2]='Groovy with <script> and <scriptdef> tasks;/usr/share/java/asm-2.jar::asm.jar /usr/share/java/asm-util-2.jar::asm-util.jar'
-#_opts[netrexx]='<netrexx> task, Rexx with <script> task;/usr/share/java/netrexx.jar'
-_opts[rhino]='Javascript with <script> task;/usr/share/java/js.jar'
-_opts[jython]='Python with <script> task;/opt/jython/jython.jar'
-#_opts[jacl]='TCL with <script> task;/usr/share/java/jacl.jar'
-#_opts[tcljava]='TCL with <script> task;/usr/share/java/tcljava.jar'
-_opts[beanshell>=1.3]='BeanShell with <script> task;/usr/share/java/bsh.jar::beanshell.jar'
-#_opts[jruby]='Ruby with <script> task;/usr/share/java/jruby.jar'
-#_opts[judo]='Judoscript with <script> task;/usr/share/java/judo.jar'
-_opts[java-commons-logging]='CommonsLoggingListener;/usr/share/java/commons-logging/commons-logging.jar'
-#_opts[java-log4j]='Log4jListener;/usr/share/java/log4j.jar'
-#_opts[java-commons-net>=1.4.0]='<ftp>, <rexec> and <telnet> tasks;/usr/share/java/commons-net.jar'
-#_opts[java-bcel]="'classfileset' data type, JavaClassHelper for ClassConstants filter reader;/usr/share/java/bcel.jar"
-#_opts[java-mail]='<mimemail> task, mime encoding with <mail>;/usr/share/java/mail.jar'
-#_opts[java-activation]='<mimemail> task, mime encoding with <mail>;/usr/share/java/activation.jar'
-#_opts[jdepend]='<jdepend> task;/usr/share/java/jdepend.jar'
-#_opts[java-xmlcommons-resolver>=1.1beta]="external files for 'xmlcatalog' datatype;/usr/share/java/resolver.jar"
-#_opts[java-jsch>=0.1.42]='<sshexec> and <scp> tasks;/usr/share/java/jsch.jar'
-#_opts[java-advanced-imaging]='<image> task/usr/share/java/jai/*.jar'
-
-for pkg in "${!_opts[@]}"; do
- optdepends+=("$pkg: ${_opts[$pkg]%;*}")
- makedepends+=("$pkg")
-done
-
-build() {
- # This directory is what becomes
- # http://archive.apache.org/dist/ant/binaries/${pkgname}-${pkgver}-bin.tar.bz2
- # which is what Arch uses
- rm -rf "${srcdir}"/${pkgname}-${pkgver}-bin
- mkdir -p "${srcdir}"/${pkgname}-${pkgver}-bin
-
- cd "${srcdir}"/${pkgname}-${pkgver}
- # Symlink to external optional libraries
- for jar in ${_opts[@]#*;}; do
- ln -sf ${jar%::*} lib/optional/`basename ${jar/*::}`
- done
- # Build
- source "/etc/profile.d/jdk.sh" # Get the JAVA_HOME env var
- sh build.sh -Ddist.dir="${srcdir}"/${pkgname}-${pkgver}-bin dist
-}
-
-package() {
- cd "${srcdir}"/${pkgname}-${pkgver}-bin
- source "${srcdir}"/${pkgname}.sh # Get the ANT_HOME env var
- source "/etc/profile.d/jdk.sh" # Get the JAVA_HOME env var
-
- ## Install profile.d script
- install -d "${pkgdir}"/etc/profile.d
- install -m755 "${srcdir}"/${pkgname}.{csh,sh} "${pkgdir}"/etc/profile.d/
-
- ## Install the main distribution
- install -d "${pkgdir}"/${ANT_HOME}
- cp -Rp * "${pkgdir}"/${ANT_HOME}
-
- ## Fix the distribution
- # Remove Windows .bat/.cmd files
- rm -f "${pkgdir}"/${ANT_HOME}/bin/*.{bat,cmd}
- # Fix python2 path
- sed -i 's|/usr/bin/python|/usr/bin/python2|' "${pkgdir}"/${ANT_HOME}/bin/runant.py
- # Symlink to external optional libraries
- for jar in ${_opts[@]#*;}; do
- ln -sf ${jar%::*} "${pkgdir}"/${ANT_HOME}/lib/`basename ${jar/*::}`
- done
-
- ## Symlink the /opt distribution to the normal places
- install -d "${pkgdir}"/usr/bin
- install -d "${pkgdir}"/usr/share/doc/${pkgname}
- install -d "${pkgdir}"/usr/share/licenses/${pkgname}
-
- cd "${pkgdir}"/${ANT_HOME}
- for prog in bin/*; do
- ln -sf ${ANT_HOME}/$prog "${pkgdir}"/usr/bin
- done
- ln -sf ${ANT_HOME}/{README,WHATSNEW} "${pkgdir}"/usr/share/doc/${pkgname}
- ln -sf ${ANT_HOME}/docs "${pkgdir}"/usr/share/doc/${pkgname}/html
- ln -sf ${ANT_HOME}/{LICENSE,NOTICE} "${pkgdir}"/usr/share/licenses/${pkgname}
-}
-
-md5sums=('c474fa9d0c35a24037c23b6e476862c1'
- 'bd63c881be406f515fc4d22635e8326a'
- 'aaa615512cbe1ed7f3b62c1ff46802f8')
diff --git a/libre/apache-ant/apache-ant.csh b/libre/apache-ant/apache-ant.csh
deleted file mode 100755
index fdc04b2f8..000000000
--- a/libre/apache-ant/apache-ant.csh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/csh
-setenv ANT_HOME /opt/apache-ant
diff --git a/libre/apache-ant/apache-ant.sh b/libre/apache-ant/apache-ant.sh
deleted file mode 100755
index 6e4809da5..000000000
--- a/libre/apache-ant/apache-ant.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-export ANT_HOME=/opt/apache-ant
diff --git a/libre/django13/PKGBUILD b/libre/django13/PKGBUILD
new file mode 100644
index 000000000..554acccc7
--- /dev/null
+++ b/libre/django13/PKGBUILD
@@ -0,0 +1,47 @@
+# $Id$
+# Maintainer: Dan McGee <dan@archlinux.org>
+# Contributor: Shahar Weiss <sweiss4@gmx.net>
+
+pkgname=django
+pkgver=1.3.1
+pkgrel=2
+pkgdesc="A high-level Python Web framework."
+arch=('any')
+license=('BSD')
+url="http://www.djangoproject.com/"
+depends=('python2')
+makedepends=('python2-distribute')
+optdepends=('mysql-python: for MySQL backend'
+ 'python2-psycopg2: for PostgreSQL backend')
+source=("https://www.djangoproject.com/m/releases/1.3/Django-$pkgver.tar.gz"
+ diff-django_branches_releases_1.3.X-from-16768-to-17460.diff)
+md5sums=('62d8642fd06b9a0bf8544178f8500767'
+ 'd09d8f9e156b9aa1b580a1b43209b99f')
+sha256sums=('af9118c4e8a063deb0b8cda901fcff2b805e7cf496c93fd43507163f3cde156b'
+ '8e08b5b5bbe7c042a1df4d5615a9d068ec6718fd00bef627c0a9a9e48ee58c15')
+
+build() {
+ cd "$srcdir/Django-$pkgver"
+ patch -Np1 -i ../diff-django_branches_releases_1.3.X-from-16768-to-17460.diff
+ python2 setup.py build
+}
+
+package() {
+ cd "$srcdir/Django-$pkgver"
+ python2 setup.py install --root="$pkgdir" --optimize=1
+
+ install -Dm644 extras/django_bash_completion \
+ "$pkgdir"/etc/bash_completion.d/django
+
+ find "$pkgdir"/usr/lib/python2.7/site-packages/django/ -name '*.py' | \
+ xargs sed -i "s|#!/usr/bin/env python$|#!/usr/bin/env python2|"
+
+ install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+_pkgname=$pkgname
+pkgname=django13
+pkgdesc+=" (legacy version for ParabolaWeb)"
+pkgrel+=.1
+provides=("$_pkgname=$pkgver")
+conflicts=("$_pkgname")
diff --git a/libre/django13/PKGBUILD.orig b/libre/django13/PKGBUILD.orig
new file mode 100644
index 000000000..c593c5626
--- /dev/null
+++ b/libre/django13/PKGBUILD.orig
@@ -0,0 +1,40 @@
+# $Id$
+# Maintainer: Dan McGee <dan@archlinux.org>
+# Contributor: Shahar Weiss <sweiss4@gmx.net>
+
+pkgname=django
+pkgver=1.3.1
+pkgrel=2
+pkgdesc="A high-level Python Web framework."
+arch=('any')
+license=('BSD')
+url="http://www.djangoproject.com/"
+depends=('python2')
+makedepends=('python2-distribute')
+optdepends=('mysql-python: for MySQL backend'
+ 'python2-psycopg2: for PostgreSQL backend')
+source=("http://media.djangoproject.com/releases/1.3/Django-$pkgver.tar.gz"
+ diff-django_branches_releases_1.3.X-from-16771-to-17460.diff)
+md5sums=('62d8642fd06b9a0bf8544178f8500767'
+ 'ea3d6cbde2fc2332ffe7f901cb60a974')
+sha256sums=('af9118c4e8a063deb0b8cda901fcff2b805e7cf496c93fd43507163f3cde156b'
+ '84e2652a8249e58fdbbd43bce7cd8d6bb2159058be6a675ebe15661ca3ee9ffc')
+
+build() {
+ cd "$srcdir/Django-$pkgver"
+ patch -Np0 < ../diff-django_branches_releases_1.3.X-from-16771-to-17460.diff
+ python2 setup.py build
+}
+
+package() {
+ cd "$srcdir/Django-$pkgver"
+ python2 setup.py install --root="$pkgdir" --optimize=1
+
+ install -Dm644 extras/django_bash_completion \
+ "$pkgdir"/etc/bash_completion.d/django
+
+ find "$pkgdir"/usr/lib/python2.7/site-packages/django/ -name '*.py' | \
+ xargs sed -i "s|#!/usr/bin/env python$|#!/usr/bin/env python2|"
+
+ install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
diff --git a/libre/django13/diff-django_branches_releases_1.3.X-from-16768-to-17460.diff b/libre/django13/diff-django_branches_releases_1.3.X-from-16768-to-17460.diff
new file mode 100644
index 000000000..c6819c1ab
--- /dev/null
+++ b/libre/django13/diff-django_branches_releases_1.3.X-from-16768-to-17460.diff
@@ -0,0 +1,1573 @@
+diff --git a/README b/README
+index c7d225c..47bfd33 100644
+--- a/README
++++ b/README
+@@ -28,7 +28,7 @@ http://code.djangoproject.com/newticket
+ To get more help:
+
+ * Join the #django channel on irc.freenode.net. Lots of helpful people
+- hang out there. Read the archives at http://botland.oebfare.com/logger/django/.
++ hang out there. Read the archives at http://django-irc-logs.com/.
+
+ * Join the django-users mailing list, or read the archives, at
+ http://groups.google.com/group/django-users.
+diff --git a/django/contrib/admin/media/css/forms.css b/django/contrib/admin/media/css/forms.css
+index 1cedf24..35d0ed7 100644
+--- a/django/contrib/admin/media/css/forms.css
++++ b/django/contrib/admin/media/css/forms.css
+@@ -352,9 +352,3 @@ fieldset.monospace textarea {
+ .empty-form {
+ display: none;
+ }
+-
+-/* IE7 specific bug fixes */
+-
+-.submit-row input {
+- float: right;
+-}
+\ No newline at end of file
+diff --git a/django/contrib/gis/db/backends/spatialite/compiler.py b/django/contrib/gis/db/backends/spatialite/compiler.py
+deleted file mode 100644
+index 3f81ae6..0000000
+--- a/django/contrib/gis/db/backends/spatialite/compiler.py
++++ /dev/null
+@@ -1,32 +0,0 @@
+-from django.db.backends.util import typecast_timestamp
+-from django.db.models.sql import compiler
+-from django.db.models.sql.constants import MULTI
+-from django.contrib.gis.db.models.sql.compiler import GeoSQLCompiler as BaseGeoSQLCompiler
+-
+-SQLCompiler = compiler.SQLCompiler
+-
+-class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler):
+- pass
+-
+-class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLUpdateCompiler(compiler.SQLUpdateCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
+- """
+- This is overridden for GeoDjango to properly cast date columns, see #16757.
+- """
+- def results_iter(self):
+- offset = len(self.query.extra_select)
+- for rows in self.execute_sql(MULTI):
+- for row in rows:
+- date = typecast_timestamp(str(row[offset]))
+- yield date
+diff --git a/django/contrib/gis/db/backends/spatialite/creation.py b/django/contrib/gis/db/backends/spatialite/creation.py
+index c107d96..ee5f9db 100644
+--- a/django/contrib/gis/db/backends/spatialite/creation.py
++++ b/django/contrib/gis/db/backends/spatialite/creation.py
+@@ -56,14 +56,6 @@ class SpatiaLiteCreation(DatabaseCreation):
+ interactive=False,
+ database=self.connection.alias)
+
+- # One effect of calling syncdb followed by flush is that the id of the
+- # default site may or may not be 1, depending on how the sequence was
+- # reset. If the sites app is loaded, then we coerce it.
+- from django.db.models import get_model
+- Site = get_model('sites', 'Site')
+- if Site is not None and Site.objects.using(self.connection.alias).count() == 1:
+- Site.objects.using(self.connection.alias).update(id=settings.SITE_ID)
+-
+ from django.core.cache import get_cache
+ from django.core.cache.backends.db import BaseDatabaseCache
+ for cache_alias in settings.CACHES:
+diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py
+index 1dc612c..e6f8409 100644
+--- a/django/contrib/gis/db/backends/spatialite/operations.py
++++ b/django/contrib/gis/db/backends/spatialite/operations.py
+@@ -48,7 +48,7 @@ def get_dist_ops(operator):
+ return (SpatiaLiteDistance(operator),)
+
+ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
+- compiler_module = 'django.contrib.gis.db.backends.spatialite.compiler'
++ compiler_module = 'django.contrib.gis.db.models.sql.compiler'
+ name = 'spatialite'
+ spatialite = True
+ version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
+diff --git a/django/contrib/gis/db/models/sql/compiler.py b/django/contrib/gis/db/models/sql/compiler.py
+index 782ce78..405a000 100644
+--- a/django/contrib/gis/db/models/sql/compiler.py
++++ b/django/contrib/gis/db/models/sql/compiler.py
+@@ -1,7 +1,7 @@
+ from itertools import izip
+-from django.db.backends.util import truncate_name
++from django.db.backends.util import truncate_name, typecast_timestamp
+ from django.db.models.sql import compiler
+-from django.db.models.sql.constants import TABLE_NAME
++from django.db.models.sql.constants import TABLE_NAME, MULTI
+ from django.db.models.sql.query import get_proxied_model
+
+ SQLCompiler = compiler.SQLCompiler
+@@ -194,7 +194,7 @@ class GeoSQLCompiler(compiler.SQLCompiler):
+ # We resolve the rest of the columns if we're on Oracle or if
+ # the `geo_values` attribute is defined.
+ for value, field in map(None, row[index_start:], fields):
+- values.append(self.query.convert_values(value, field, connection=self.connection))
++ values.append(self.query.convert_values(value, field, self.connection))
+ else:
+ values.extend(row[index_start:])
+ return tuple(values)
+@@ -275,4 +275,24 @@ class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
+ pass
+
+ class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
+- pass
++ """
++ This is overridden for GeoDjango to properly cast date columns, since
++ `GeoQuery.resolve_columns` is used for spatial values.
++ See #14648, #16757.
++ """
++ def results_iter(self):
++ if self.connection.ops.oracle:
++ from django.db.models.fields import DateTimeField
++ fields = [DateTimeField()]
++ else:
++ needs_string_cast = self.connection.features.needs_datetime_string_cast
++
++ offset = len(self.query.extra_select)
++ for rows in self.execute_sql(MULTI):
++ for row in rows:
++ date = row[offset]
++ if self.connection.ops.oracle:
++ date = self.resolve_columns(row, fields)[offset]
++ elif needs_string_cast:
++ date = typecast_timestamp(str(date))
++ yield date
+diff --git a/django/contrib/gis/tests/relatedapp/fixtures/initial_data.json.gz b/django/contrib/gis/tests/relatedapp/fixtures/initial_data.json.gz
+index 68bf54c..8937637 100644
+Binary files a/django/contrib/gis/tests/relatedapp/fixtures/initial_data.json.gz and b/django/contrib/gis/tests/relatedapp/fixtures/initial_data.json.gz differ
+diff --git a/django/contrib/gis/tests/relatedapp/models.py b/django/contrib/gis/tests/relatedapp/models.py
+index 2e9a62b..aec4e15 100644
+--- a/django/contrib/gis/tests/relatedapp/models.py
++++ b/django/contrib/gis/tests/relatedapp/models.py
+@@ -36,6 +36,7 @@ class Parcel(models.Model):
+ # These use the GeoManager but do not have any geographic fields.
+ class Author(models.Model):
+ name = models.CharField(max_length=100)
++ dob = models.DateField()
+ objects = models.GeoManager()
+
+ class Article(models.Model):
+diff --git a/django/contrib/gis/tests/relatedapp/tests.py b/django/contrib/gis/tests/relatedapp/tests.py
+index 250783b..1a6197c 100644
+--- a/django/contrib/gis/tests/relatedapp/tests.py
++++ b/django/contrib/gis/tests/relatedapp/tests.py
+@@ -1,3 +1,4 @@
++from datetime import date
+ from django.test import TestCase
+
+ from django.contrib.gis.geos import GEOSGeometry, Point, MultiPoint
+@@ -281,4 +282,11 @@ class RelatedGeoModelTest(TestCase):
+ # evaluated as list generation swallows TypeError in CPython.
+ sql = str(qs.query)
+
++ def test16_annotated_date_queryset(self):
++ "Ensure annotated date querysets work if spatial backend is used. See #14648."
++ birth_years = [dt.year for dt in
++ list(Author.objects.annotate(num_books=Count('books')).dates('dob', 'year'))]
++ birth_years.sort()
++ self.assertEqual([1950, 1974], birth_years)
++
+ # TODO: Related tests for KML, GML, and distance lookups.
+diff --git a/django/contrib/sites/management.py b/django/contrib/sites/management.py
+index 1987274..9bf5a14 100644
+--- a/django/contrib/sites/management.py
++++ b/django/contrib/sites/management.py
+@@ -3,15 +3,34 @@ Creates the default Site object.
+ """
+
+ from django.db.models import signals
++from django.db import connections
++from django.db import router
+ from django.contrib.sites.models import Site
+ from django.contrib.sites import models as site_app
++from django.core.management.color import no_style
+
+ def create_default_site(app, created_models, verbosity, db, **kwargs):
+- if Site in created_models:
++ # Only create the default sites in databases where Django created the table
++ if Site in created_models and router.allow_syncdb(db, Site) :
++ # The default settings set SITE_ID = 1, and some tests in Django's test
++ # suite rely on this value. However, if database sequences are reused
++ # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that
++ # the next id will be 1, so we coerce it. See #15573 and #16353. This
++ # can also crop up outside of tests - see #15346.
+ if verbosity >= 2:
+ print "Creating example.com Site object"
+- s = Site(domain="example.com", name="example.com")
+- s.save(using=db)
++ Site(pk=1, domain="example.com", name="example.com").save(using=db)
++
++ # We set an explicit pk instead of relying on auto-incrementation,
++ # so we need to reset the database sequence.
++ sequence_sql = connections[db].ops.sequence_reset_sql(no_style(), [Site])
++ if sequence_sql:
++ if verbosity >= 2:
++ print "Resetting sequence"
++ cursor = connections[db].cursor()
++ for command in sequence_sql:
++ cursor.execute(command)
++
+ Site.objects.clear_cache()
+
+ signals.post_syncdb.connect(create_default_site, sender=site_app)
+diff --git a/django/contrib/sites/tests.py b/django/contrib/sites/tests.py
+index 17ab1f2..828badb 100644
+--- a/django/contrib/sites/tests.py
++++ b/django/contrib/sites/tests.py
+@@ -15,6 +15,12 @@ class SitesFrameworkTests(TestCase):
+ def tearDown(self):
+ Site._meta.installed = self.old_Site_meta_installed
+
++ def test_save_another(self):
++ # Regression for #17415
++ # On some backends the sequence needs reset after save with explicit ID.
++ # Test that there is no sequence collisions by saving another site.
++ Site(domain="example2.com", name="example2.com").save()
++
+ def test_site_manager(self):
+ # Make sure that get_current() does not return a deleted Site object.
+ s = Site.objects.get_current()
+diff --git a/django/core/management/commands/shell.py b/django/core/management/commands/shell.py
+index e4ce462..039ebb8 100644
+--- a/django/core/management/commands/shell.py
++++ b/django/core/management/commands/shell.py
+@@ -13,9 +13,8 @@ class Command(NoArgsCommand):
+
+ def ipython(self):
+ try:
+- from IPython.frontend.terminal.embed import TerminalInteractiveShell
+- shell = TerminalInteractiveShell()
+- shell.mainloop()
++ from IPython import embed
++ embed()
+ except ImportError:
+ # IPython < 0.11
+ # Explicitly pass an empty list as arguments, because otherwise
+diff --git a/django/core/validators.py b/django/core/validators.py
+index a93c6ac..9dcc2bc 100644
+--- a/django/core/validators.py
++++ b/django/core/validators.py
+@@ -147,7 +147,8 @@ class EmailValidator(RegexValidator):
+
+ email_re = re.compile(
+ r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
+- r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
++ # quoted-string, see also http://tools.ietf.org/html/rfc2822#section-3.2.5
++ r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
+ r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE) # domain
+ validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')
+
+diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py
+index 57e3f77..ef594b7 100644
+--- a/django/db/backends/creation.py
++++ b/django/db/backends/creation.py
+@@ -374,15 +374,6 @@ class BaseDatabaseCreation(object):
+ verbosity=max(verbosity - 1, 0),
+ interactive=False,
+ database=self.connection.alias)
+-
+- # One effect of calling syncdb followed by flush is that the id of the
+- # default site may or may not be 1, depending on how the sequence was
+- # reset. If the sites app is loaded, then we coerce it.
+- from django.db.models import get_model
+- if 'django.contrib.sites' in settings.INSTALLED_APPS:
+- Site = get_model('sites', 'Site')
+- if Site is not None and Site.objects.using(self.connection.alias).count() == 1:
+- Site.objects.using(self.connection.alias).update(id=settings.SITE_ID)
+
+ from django.core.cache import get_cache
+ from django.core.cache.backends.db import BaseDatabaseCache
+diff --git a/django/http/__init__.py b/django/http/__init__.py
+index 68ac45d..07e5a46 100644
+--- a/django/http/__init__.py
++++ b/django/http/__init__.py
+@@ -92,7 +92,7 @@ else:
+ if not _cookie_allows_colon_in_names:
+ def load(self, rawdata, ignore_parse_errors=False):
+ if ignore_parse_errors:
+- self.bad_cookies = []
++ self.bad_cookies = set()
+ self._BaseCookie__set = self._loose_set
+ super(SimpleCookie, self).load(rawdata)
+ if ignore_parse_errors:
+@@ -106,8 +106,8 @@ else:
+ try:
+ self._strict_set(key, real_value, coded_value)
+ except Cookie.CookieError:
+- self.bad_cookies.append(key)
+- dict.__setitem__(self, key, None)
++ self.bad_cookies.add(key)
++ dict.__setitem__(self, key, Cookie.Morsel())
+
+
+ class CompatCookie(SimpleCookie):
+diff --git a/django/http/utils.py b/django/http/utils.py
+index 5eea239..0180864 100644
+--- a/django/http/utils.py
++++ b/django/http/utils.py
+@@ -76,7 +76,8 @@ def fix_IE_for_vary(request, response):
+
+ # The first part of the Content-Type field will be the MIME type,
+ # everything after ';', such as character-set, can be ignored.
+- if response['Content-Type'].split(';')[0] not in safe_mime_types:
++ mime_type = response.get('Content-Type', '').partition(';')[0]
++ if mime_type not in safe_mime_types:
+ try:
+ del response['Vary']
+ except KeyError:
+diff --git a/docs/howto/deployment/modpython.txt b/docs/howto/deployment/modpython.txt
+index f5030e9..693f942 100644
+--- a/docs/howto/deployment/modpython.txt
++++ b/docs/howto/deployment/modpython.txt
+@@ -293,11 +293,14 @@ of the admin app, but this is not the case when you use any other server
+ arrangement. You're responsible for setting up Apache, or whichever media
+ server you're using, to serve the admin files.
+
+-The admin files live in (:file:`django/contrib/admin/static/admin`) of the
++The admin files live in (:file:`django/contrib/admin/media/admin`) of the
+ Django distribution.
+
+-We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle
+-the admin files, but here are two other approaches:
++We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle the
++admin files (this means using the :djadmin:`collectstatic` management command
++to collect the static files in :setting:`STATIC_ROOT`, and then configuring
++your webserver to serve :setting:`STATIC_ROOT` at :setting:`STATIC_URL`), but
++here are two other approaches:
+
+ 1. Create a symbolic link to the admin static files from within your
+ document root.
+diff --git a/docs/howto/deployment/modwsgi.txt b/docs/howto/deployment/modwsgi.txt
+index de3a5b6..fdf9d27 100644
+--- a/docs/howto/deployment/modwsgi.txt
++++ b/docs/howto/deployment/modwsgi.txt
+@@ -127,11 +127,14 @@ of the admin app, but this is not the case when you use any other server
+ arrangement. You're responsible for setting up Apache, or whichever media
+ server you're using, to serve the admin files.
+
+-The admin files live in (:file:`django/contrib/admin/static/admin`) of the
++The admin files live in (:file:`django/contrib/admin/media/admin`) of the
+ Django distribution.
+
+-We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle
+-the admin files, but here are two other approaches:
++We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle the
++admin files (this means using the :djadmin:`collectstatic` management command
++to collect the static files in :setting:`STATIC_ROOT`, and then configuring
++your webserver to serve :setting:`STATIC_ROOT` at :setting:`STATIC_URL`), but
++here are two other approaches:
+
+ 1. Create a symbolic link to the admin static files from within your
+ document root.
+diff --git a/docs/index.txt b/docs/index.txt
+index 0cf066e..20a7cec 100644
+--- a/docs/index.txt
++++ b/docs/index.txt
+@@ -28,7 +28,7 @@ Having trouble? We'd like to help!
+ .. _archives of the django-users mailing list: http://groups.google.com/group/django-users/
+ .. _post a question: http://groups.google.com/group/django-users/
+ .. _#django IRC channel: irc://irc.freenode.net/django
+-.. _IRC logs: http://botland.oebfare.com/logger/django/
++.. _IRC logs: http://django-irc-logs.com/
+ .. _ticket tracker: http://code.djangoproject.com/
+
+ First steps
+diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
+index 3f0f998..ca29d15 100644
+--- a/docs/internals/deprecation.txt
++++ b/docs/internals/deprecation.txt
+@@ -177,6 +177,12 @@ their deprecation, as per the :ref:`Django deprecation policy
+ required to end with a trailing slash to ensure there is a consistent
+ way to combine paths in templates.
+
++ * Translations located under the so-called *project path* will be
++ ignored during the translation building process performed at runtime.
++ The :setting:`LOCALE_PATHS` setting can be used for the same task by
++ including the filesystem path to a ``locale`` directory containing
++ non-app-specific translations in its value.
++
+ * 2.0
+ * ``django.views.defaults.shortcut()``. This function has been moved
+ to ``django.contrib.contenttypes.views.shortcut()`` as part of the
+diff --git a/docs/internals/release-process.txt b/docs/internals/release-process.txt
+index 2a56f0b..799a59e 100644
+--- a/docs/internals/release-process.txt
++++ b/docs/internals/release-process.txt
+@@ -99,6 +99,13 @@ varying levels:
+ * Security fixes will be applied to the current trunk and the previous two
+ minor releases.
+
++* Documentation fixes will generally be more freely backported to the last
++ release branch (at the discretion of the committer), and don't need to meet
++ the "critical fixes only" bar as it's highly advantageous to have the docs
++ for the last release be up-to-date and correct, and the downside of
++ backporting (risk of introducing regressions) is much less of a concern
++ with doc fixes.
++
+ As a concrete example, consider a moment in time halfway between the release of
+ Django 1.3 and 1.4. At this point in time:
+
+@@ -111,6 +118,9 @@ Django 1.3 and 1.4. At this point in time:
+ ``1.2.X`` branch. Security fixes will trigger the release of ``1.3.1``,
+ ``1.2.1``, etc.
+
++* Documentation fixes will be applied to trunk, and if easily backported, to
++ the ``1.3.X`` branch.
++
+ .. _release-process:
+
+ Release process
+diff --git a/docs/intro/index.txt b/docs/intro/index.txt
+index bc61be7..19290a5 100644
+--- a/docs/intro/index.txt
++++ b/docs/intro/index.txt
+@@ -31,6 +31,6 @@ place: read this material to quickly get up and running.
+
+ .. _python: http://python.org/
+ .. _list of Python resources for non-programmers: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers
+- .. _dive into python: http://diveintopython.org/
++ .. _dive into python: http://diveintopython.net/
+ .. _dead-tree version: http://www.amazon.com/exec/obidos/ASIN/1590593561/ref=nosim/jacobian20
+ .. _books about Python: http://wiki.python.org/moin/PythonBooks
+\ No newline at end of file
+diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt
+index 2f2e049..4dc1e5c 100644
+--- a/docs/intro/tutorial01.txt
++++ b/docs/intro/tutorial01.txt
+@@ -59,7 +59,7 @@ This will create a ``mysite`` directory in your current directory.
+ can be run as a program. To do this, open Terminal.app and navigate (using
+ the ``cd`` command) to the directory where :doc:`django-admin.py
+ </ref/django-admin>` is installed, then run the command
+- ``chmod +x django-admin.py``.
++ ``sudo chmod +x django-admin.py``.
+
+ .. note::
+
+@@ -692,10 +692,9 @@ Save these changes and start a new Python interactive shell by running
+
+ For more information on model relations, see :doc:`Accessing related objects
+ </ref/models/relations>`. For more on how to use double underscores to perform
+-field lookups via the API, see `Field lookups`__. For full details on the
+-database API, see our :doc:`Database API reference </topics/db/queries>`.
+-
+-__ http://docs.djangoproject.com/en/1.2/topics/db/queries/#field-lookups
++field lookups via the API, see :ref:`Field lookups <field-lookups-intro>`. For
++full details on the database API, see our :doc:`Database API reference
++</topics/db/queries>`.
+
+ When you're comfortable with the API, read :doc:`part 2 of this tutorial
+ </intro/tutorial02>` to get Django's automatic admin working.
+diff --git a/docs/intro/tutorial02.txt b/docs/intro/tutorial02.txt
+index 4bd31fb..1e837e6 100644
+--- a/docs/intro/tutorial02.txt
++++ b/docs/intro/tutorial02.txt
+@@ -40,22 +40,22 @@ activate the admin site for your installation, do these three things:
+
+ .. parsed-literal::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ # Uncomment the next two lines to enable the admin:
+ **from django.contrib import admin**
+ **admin.autodiscover()**
+
+ urlpatterns = patterns('',
+- # Example:
+- # (r'^mysite/', include('mysite.foo.urls')),
++ # Examples:
++ # url(r'^$', 'mysite.views.home', name='home'),
++ # url(r'^mysite/', include('mysite.foo.urls')),
+
+- # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+- # to INSTALLED_APPS to enable admin documentation:
+- # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
++ # Uncomment the admin/doc line below to enable admin documentation:
++ # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ # Uncomment the next line to enable the admin:
+- **(r'^admin/', include(admin.site.urls)),**
++ **url(r'^admin/', include(admin.site.urls)),**
+ )
+
+ (The bold lines are the ones that needed to be uncommented.)
+diff --git a/docs/intro/tutorial03.txt b/docs/intro/tutorial03.txt
+index 41a62a7..566ba55 100644
+--- a/docs/intro/tutorial03.txt
++++ b/docs/intro/tutorial03.txt
+@@ -78,17 +78,17 @@ point at that file::
+
+ Time for an example. Edit ``mysite/urls.py`` so it looks like this::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ from django.contrib import admin
+ admin.autodiscover()
+
+ urlpatterns = patterns('',
+- (r'^polls/$', 'polls.views.index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
+- (r'^admin/', include(admin.site.urls)),
++ url(r'^polls/$', 'polls.views.index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
++ url(r'^admin/', include(admin.site.urls)),
+ )
+
+ This is worth a review. When somebody requests a page from your Web site -- say,
+@@ -112,7 +112,7 @@ what you can do with them. And there's no need to add URL cruft such as ``.php``
+ -- unless you have a sick sense of humor, in which case you can do something
+ like this::
+
+- (r'^polls/latest\.php$', 'polls.views.index'),
++ url(r'^polls/latest\.php$', 'polls.views.index'),
+
+ But, don't do that. It's silly.
+
+@@ -357,22 +357,23 @@ the list is empty.
+ Write a 404 (page not found) view
+ =================================
+
+-When you raise :exc:`~django.http.Http404` from within a view, Django will load
+-a special view devoted to handling 404 errors. It finds it by looking for the
+-variable ``handler404``, which is a string in Python dotted syntax -- the same
+-format the normal URLconf callbacks use. A 404 view itself has nothing special:
+-It's just a normal view.
+-
+-You normally won't have to bother with writing 404 views. By default, URLconfs
+-have the following line up top::
+-
+- from django.conf.urls.defaults import *
++When you raise :exc:`~django.http.Http404` from within a view, Django
++will load a special view devoted to handling 404 errors. It finds it
++by looking for the variable ``handler404`` in your root URLconf (and
++only in your root URLconf; setting ``handler404`` anywhere else will
++have no effect), which is a string in Python dotted syntax -- the same
++format the normal URLconf callbacks use. A 404 view itself has nothing
++special: It's just a normal view.
+
+-That takes care of setting ``handler404`` in the current module. As you can see
+-in ``django/conf/urls/defaults.py``, ``handler404`` is set to
+-:func:`django.views.defaults.page_not_found` by default.
++You normally won't have to bother with writing 404 views. If you don't set
++``handler404``, the built-in view :func:`django.views.defaults.page_not_found`
++is used by default. In this case, you still have one obligation: To create a
++``404.html`` template in the root of your template directory. The default 404
++view will use that template for all 404 errors. If :setting:`DEBUG` is set to
++``False`` (in your settings module) and if you didn't create a ``404.html``
++file, an ``Http500`` is raised instead. So remember to create a ``404.html``.
+
+-Four more things to note about 404 views:
++A couple more things to note about 404 views:
+
+ * If :setting:`DEBUG` is set to ``True`` (in your settings module) then your
+ 404 view will never be used (and thus the ``404.html`` template will never
+@@ -381,21 +382,12 @@ Four more things to note about 404 views:
+ * The 404 view is also called if Django doesn't find a match after checking
+ every regular expression in the URLconf.
+
+- * If you don't define your own 404 view -- and simply use the default, which
+- is recommended -- you still have one obligation: To create a ``404.html``
+- template in the root of your template directory. The default 404 view will
+- use that template for all 404 errors.
+-
+- * If :setting:`DEBUG` is set to ``False`` (in your settings module) and if
+- you didn't create a ``404.html`` file, an ``Http500`` is raised instead.
+- So remember to create a ``404.html``.
+-
+ Write a 500 (server error) view
+ ===============================
+
+-Similarly, URLconfs may define a ``handler500``, which points to a view to call
+-in case of server errors. Server errors happen when you have runtime errors in
+-view code.
++Similarly, your root URLconf may define a ``handler500``, which points
++to a view to call in case of server errors. Server errors happen when
++you have runtime errors in view code.
+
+ Use the template system
+ =======================
+@@ -432,10 +424,10 @@ Take some time to play around with the views and template system. As you edit
+ the URLconf, you may notice there's a fair bit of redundancy in it::
+
+ urlpatterns = patterns('',
+- (r'^polls/$', 'polls.views.index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
++ url(r'^polls/$', 'polls.views.index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
+ )
+
+ Namely, ``polls.views`` is in every callback.
+@@ -445,10 +437,10 @@ common prefixes. You can factor out the common prefixes and add them as the
+ first argument to :func:`~django.conf.urls.defaults.patterns`, like so::
+
+ urlpatterns = patterns('polls.views',
+- (r'^polls/$', 'index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^polls/$', 'index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ This is functionally identical to the previous formatting. It's just a bit
+@@ -459,20 +451,20 @@ callback in your URLconf, you can concatenate multiple
+ :func:`~django.conf.urls.defaults.patterns`. Your full ``mysite/urls.py`` might
+ now look like this::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ from django.contrib import admin
+ admin.autodiscover()
+
+ urlpatterns = patterns('polls.views',
+- (r'^polls/$', 'index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^polls/$', 'index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ urlpatterns += patterns('',
+- (r'^admin/', include(admin.site.urls)),
++ url(r'^admin/', include(admin.site.urls)),
+ )
+
+ Decoupling the URLconfs
+@@ -502,8 +494,8 @@ Copy the file ``mysite/urls.py`` to ``polls/urls.py``. Then, change
+ admin.autodiscover()
+
+ urlpatterns = patterns('',
+- (r'^polls/', include('polls.urls')),
+- (r'^admin/', include(admin.site.urls)),
++ url(r'^polls/', include('polls.urls')),
++ url(r'^admin/', include(admin.site.urls)),
+ )
+
+ :func:`~django.conf.urls.defaults.include` simply references another URLconf.
+@@ -526,13 +518,13 @@ URLconf by removing the leading "polls/" from each line, and removing the
+ lines registering the admin site. Your ``polls/urls.py`` file should now look like
+ this::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ urlpatterns = patterns('polls.views',
+- (r'^$', 'index'),
+- (r'^(?P<poll_id>\d+)/$', 'detail'),
+- (r'^(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^$', 'index'),
++ url(r'^(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ The idea behind :func:`~django.conf.urls.defaults.include` and URLconf
+diff --git a/docs/intro/tutorial04.txt b/docs/intro/tutorial04.txt
+index ded5cb2..4c2f2d4 100644
+--- a/docs/intro/tutorial04.txt
++++ b/docs/intro/tutorial04.txt
+@@ -218,13 +218,13 @@ Read on for details.
+ First, open the ``polls/urls.py`` URLconf. It looks like this, according to the
+ tutorial so far::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ urlpatterns = patterns('polls.views',
+- (r'^$', 'index'),
+- (r'^(?P<poll_id>\d+)/$', 'detail'),
+- (r'^(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^$', 'index'),
++ url(r'^(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ Change it like so::
+@@ -234,12 +234,12 @@ Change it like so::
+ from polls.models import Poll
+
+ urlpatterns = patterns('',
+- (r'^$',
++ url(r'^$',
+ ListView.as_view(
+ queryset=Poll.objects.order_by('-pub_date')[:5],
+ context_object_name='latest_poll_list',
+ template_name='polls/index.html')),
+- (r'^(?P<pk>\d+)/$',
++ url(r'^(?P<pk>\d+)/$',
+ DetailView.as_view(
+ model=Poll,
+ template_name='polls/detail.html')),
+@@ -248,7 +248,7 @@ Change it like so::
+ model=Poll,
+ template_name='polls/results.html'),
+ name='poll_results'),
+- (r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
++ url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
+ )
+
+ We're using two generic views here:
+diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
+index beff94e..7394c3a 100644
+--- a/docs/ref/contrib/admin/index.txt
++++ b/docs/ref/contrib/admin/index.txt
+@@ -19,8 +19,10 @@ There are six steps in activating the Django admin site:
+ 1. Add ``'django.contrib.admin'`` to your :setting:`INSTALLED_APPS`
+ setting.
+
+- 2. Admin has two dependencies - :mod:`django.contrib.auth` and
+- :mod:`django.contrib.contenttypes`. If these applications are not
++ 2. The admin has four dependencies - :mod:`django.contrib.auth`,
++ :mod:`django.contrib.contenttypes`,
++ :mod:`django.contrib.messages` and
++ :mod:`django.contrib.sessions`. If these applications are not
+ in your :setting:`INSTALLED_APPS` list, add them.
+
+ 3. Determine which of your application's models should be editable in the
+@@ -542,7 +544,7 @@ subclass::
+ Fields in ``list_filter`` can also span relations using the ``__`` lookup::
+
+ class UserAdminWithLookup(UserAdmin):
+- list_filter = ('groups__name')
++ list_filter = ('groups__name',)
+
+ .. attribute:: ModelAdmin.list_per_page
+
+diff --git a/docs/ref/contrib/gis/geoip.txt b/docs/ref/contrib/gis/geoip.txt
+index 6503be7..f5c45e1 100644
+--- a/docs/ref/contrib/gis/geoip.txt
++++ b/docs/ref/contrib/gis/geoip.txt
+@@ -144,7 +144,7 @@ parameters.
+ Returns a dictionary of city information for the given query. Some
+ of the values in the dictionary may be undefined (``None``).
+
+-.. method:: GeoIPcountry(query)
++.. method:: GeoIP.country(query)
+
+ Returns a dictionary with the country code and country for the given
+ query.
+diff --git a/docs/ref/contrib/messages.txt b/docs/ref/contrib/messages.txt
+index ca3212d..ee7e01c 100644
+--- a/docs/ref/contrib/messages.txt
++++ b/docs/ref/contrib/messages.txt
+@@ -210,6 +210,10 @@ If you're using the context processor, your template should be rendered with a
+ ``RequestContext``. Otherwise, ensure ``messages`` is available to
+ the template context.
+
++Even if you know there is only just one message, you should still iterate over
++the ``messages`` sequence, because otherwise the message storage will not be cleared
++for the next request.
++
+ Creating custom message levels
+ ------------------------------
+
+diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
+index 89bc43f..58b86ea 100644
+--- a/docs/ref/django-admin.txt
++++ b/docs/ref/django-admin.txt
+@@ -1156,7 +1156,7 @@ variable.
+ Note that this option is unnecessary in ``manage.py``, because it takes care of
+ setting the Python path for you.
+
+-.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
++.. _import search path: http://diveintopython.net/getting_to_know_python/everything_is_an_object.html
+
+ .. django-admin-option:: --settings
+
+diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
+index 3728a09..52c0869 100644
+--- a/docs/ref/models/instances.txt
++++ b/docs/ref/models/instances.txt
+@@ -470,7 +470,7 @@ the URL. For example, if your URLconf contained a line such as::
+
+ Similarly, if you had a URLconf entry that looked like::
+
+- (r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', archive_view)
++ (r'/archive/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', archive_view)
+
+ ...you could reference this using ``permalink()`` as follows::
+
+@@ -478,8 +478,8 @@ Similarly, if you had a URLconf entry that looked like::
+ def get_absolute_url(self):
+ return ('archive_view', (), {
+ 'year': self.created.year,
+- 'month': self.created.month,
+- 'day': self.created.day})
++ 'month': self.created.strftime('%m'),
++ 'day': self.created.strftime('%d')})
+
+ Notice that we specify an empty sequence for the second parameter in this case,
+ because we only want to pass keyword parameters, not positional ones.
+diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
+index 4530439..c1beab0 100644
+--- a/docs/ref/models/options.txt
++++ b/docs/ref/models/options.txt
+@@ -166,6 +166,13 @@ Django quotes column and table names behind the scenes.
+ >>> answer.get_previous_in_order()
+ <Answer: 1>
+
++.. admonition:: Changing order_with_respect_to
++
++ ``order_with_respect_to`` adds an additional field/database column
++ named ``_order``, so be sure to handle that as you would any other
++ change to your models if you add or change ``order_with_respect_to``
++ after your initial :djadmin:`syncdb`.
++
+ ``ordering``
+ ------------
+
+@@ -238,6 +245,12 @@ Django quotes column and table names behind the scenes.
+
+ unique_together = ("driver", "restaurant")
+
++ A :class:`~django.db.models.ManyToManyField` cannot be included in
++ unique_together (it's not even clear what that would mean). If you
++ need to validate uniqueness related to a
++ :class:`~django.db.models.ManyToManyField`, look at signals or
++ using an explicit :attr:`through <ManyToManyField.through>` model.
++
+ ``verbose_name``
+ ----------------
+
+diff --git a/docs/ref/signals.txt b/docs/ref/signals.txt
+index e83142e..ad25dce 100644
+--- a/docs/ref/signals.txt
++++ b/docs/ref/signals.txt
+@@ -352,12 +352,16 @@ post_syncdb
+ .. data:: django.db.models.signals.post_syncdb
+ :module:
+
+-Sent by :djadmin:`syncdb` after it installs an application.
++Sent by :djadmin:`syncdb` command after it installs an application, and
++:djadmin:`flush` command.
+
+ Any handlers that listen to this signal need to be written in a particular
+ place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If
+ handlers are registered anywhere else they may not be loaded by
+-:djadmin:`syncdb`.
++:djadmin:`syncdb`. It is important that handlers of this signal perform
++idempotent changes (e.g. no database alterations) as this may cause the
++:djadmin:`flush` management command to fail if it also ran during the
++:djadmin:`syncdb` command.
+
+ Arguments sent with this signal:
+
+diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
+index 7d24c1d..6c7057a 100644
+--- a/docs/ref/templates/builtins.txt
++++ b/docs/ref/templates/builtins.txt
+@@ -1868,7 +1868,7 @@ slice
+ Returns a slice of the list.
+
+ Uses the same syntax as Python's list slicing. See
+-http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice
++http://diveintopython.net/native_data_types/lists.html#odbchelper.list.slice
+ for an introduction.
+
+ Example::
+diff --git a/docs/releases/0.95.txt b/docs/releases/0.95.txt
+index 7409bff..3632c31 100644
+--- a/docs/releases/0.95.txt
++++ b/docs/releases/0.95.txt
+@@ -92,15 +92,15 @@ changes is described in the `Removing The Magic`_ wiki page. There is also an
+ easy checklist_ for reference when undertaking the porting operation.
+
+ .. _Removing The Magic: http://code.djangoproject.com/wiki/RemovingTheMagic
+-.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet1
++.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet
+
+ Problem reports and getting help
+ ================================
+
+-Need help resolving a problem with Django? The documentation in the distribution
+-is also available online_ at the `Django Web site`_. The :doc:`FAQ </faq/index>`
+-document is especially recommended, as it contains a number of issues that come
+-up time and again.
++Need help resolving a problem with Django? The documentation in the
++distribution is also available :doc:`online </index>` at the `Django Web
++site`_. The :doc:`FAQ </faq/index>` document is especially recommended, as it
++contains a number of issues that come up time and again.
+
+ For more personalized help, the `django-users`_ mailing list is a very active
+ list, with more than 2,000 subscribers who can help you solve any sort of
+@@ -113,7 +113,6 @@ there's a #django channel on irc.freenode.net that is regularly populated by
+ Django users and developers from around the world. Friendly people are usually
+ available at any hour of the day -- to help, or just to chat.
+
+-.. _online: http://www.djangoproject.com/documentation/0.95/
+ .. _Django Web site: http://www.djangoproject.com/
+ .. _django-users: http://groups.google.com/group/django-users
+
+diff --git a/docs/releases/0.96.txt b/docs/releases/0.96.txt
+index 1224360..8874ccb 100644
+--- a/docs/releases/0.96.txt
++++ b/docs/releases/0.96.txt
+@@ -50,12 +50,10 @@ aside from any necessary security fixes, it will not be actively
+ maintained, and it will be removed in a future release of Django.
+
+ Also, note that some features, like the new :setting:`DATABASE_OPTIONS`
+-setting (see the `databases documentation`_ for details), are only
+-available on the "mysql" backend, and will not be made available for
++setting (see the :doc:`databases documentation </ref/databases>` for details),
++are only available on the "mysql" backend, and will not be made available for
+ "mysql_old".
+
+-.. _databases documentation: http://www.djangoproject.com/documentation/0.96/databases/
+-
+ Database constraint names changed
+ ---------------------------------
+
+@@ -164,10 +162,8 @@ Although the ``newforms`` library will continue to evolve, it's ready for use
+ for most common cases. We recommend that anyone new to form handling skip the
+ old forms system and start with the new.
+
+-For more information about ``django.newforms``, read the `newforms
+-documentation`_.
+-
+-.. _newforms documentation: http://www.djangoproject.com/documentation/0.96/newforms/
++For more information about ``django.newforms``, read the :doc:`newforms
++documentation </topics/forms/index>`.
+
+ URLconf improvements
+ --------------------
+@@ -216,19 +212,15 @@ The test framework
+ ------------------
+
+ Django now includes a test framework so you can start transmuting fear into
+-boredom (with apologies to Kent Beck). You can write tests based on doctest_
+-or unittest_ and test your views with a simple test client.
++boredom (with apologies to Kent Beck). You can write tests based on
++:mod:`doctest` or :mod:`unittest` and test your views with a simple test client.
+
+ There is also new support for "fixtures" -- initial data, stored in any of the
+-supported `serialization formats`_, that will be loaded into your database at the
+-start of your tests. This makes testing with real data much easier.
+-
+-See `the testing documentation`_ for the full details.
++supported :doc:`serialization formats </topics/serialization>`, that will be
++loaded into your database at the start of your tests. This makes testing with
++real data much easier.
+
+-.. _doctest: http://docs.python.org/library/doctest.html
+-.. _unittest: http://docs.python.org/library/unittest.html
+-.. _the testing documentation: http://www.djangoproject.com/documentation/0.96/testing/
+-.. _serialization formats: http://www.djangoproject.com/documentation/0.96/serialization/
++See :doc:`the testing documentation </topics/testing>` for the full details.
+
+ Improvements to the admin interface
+ -----------------------------------
+diff --git a/docs/releases/1.0.1.txt b/docs/releases/1.0.1.txt
+index 780dc53..3550e7c 100644
+--- a/docs/releases/1.0.1.txt
++++ b/docs/releases/1.0.1.txt
+@@ -6,10 +6,10 @@ Welcome to Django 1.0.1!
+
+ This is the first "bugfix" release in the Django 1.0 series, improving
+ the stability and performance of the Django 1.0 codebase. As such,
+-Django 1.0.1 contains no new features (and, pursuant to `our
+-compatibility policy`_, maintains backwards compatibility with Django
+-1.0), but does contain a number of fixes and other
+-improvements. Django 1.0.1 is a recommended upgrade for any
++Django 1.0.1 contains no new features (and, pursuant to :doc:`our
++compatibility policy </misc/api-stability/>`, maintains backwards
++compatibility with Django 1.0), but does contain a number of fixes
++and other improvements. Django 1.0.1 is a recommended upgrade for any
+ development or deployment currently using or targeting Django 1.0.
+
+
+@@ -46,8 +46,9 @@ highlights:
+
+ * A fix to the application of autoescaping for literal strings passed
+ to the ``join`` template filter. Previously, literal strings passed
+- to ``join`` were automatically escaped, contrary to `the documented
+- behavior for autoescaping and literal strings`_. Literal strings
++ to ``join`` were automatically escaped, contrary to :ref:`the
++ documented behavior for autoescaping and literal strings
++ <string-literals-and-automatic-escaping>`. Literal strings
+ passed to ``join`` are no longer automatically escaped, meaning you
+ must now manually escape them; this is an incompatibility if you
+ were relying on this bug, but not if you were relying on escaping
+@@ -60,6 +61,4 @@ highlights:
+ documentation, including both corrections to existing documents and
+ expanded and new documentation.
+
+-.. _our compatibility policy: http://docs.djangoproject.com/en/dev/misc/api-stability/
+ .. _the Subversion log of the 1.0.X branch: http://code.djangoproject.com/log/django/branches/releases/1.0.X
+-.. _the documented behavior for autoescaping and literal strings: http://docs.djangoproject.com/en/dev/topics/templates/#string-literals-and-automatic-escaping
+diff --git a/docs/releases/1.2.6.txt b/docs/releases/1.2.6.txt
+new file mode 100644
+index 0000000..cfd1d9c
+--- /dev/null
++++ b/docs/releases/1.2.6.txt
+@@ -0,0 +1,16 @@
++==========================
++Django 1.2.6 release notes
++==========================
++
++*September 9, 2011*
++
++Welcome to Django 1.2.6!
++
++This is the sixth bugfix/security release in the Django 1.2 series, fixing
++several security issues present in Django 1.2.5. Django 1.2.6 is a
++recommended upgrade for all users of any Django release in the 1.2.X series.
++
++For a full list of issues addressed in this release, see the `security
++advisory`_.
++
++.. _security advisory: https://www.djangoproject.com/weblog/2011/sep/09/security-releases-issued/
+diff --git a/docs/releases/1.2.7.txt b/docs/releases/1.2.7.txt
+new file mode 100644
+index 0000000..c0cf698
+--- /dev/null
++++ b/docs/releases/1.2.7.txt
+@@ -0,0 +1,16 @@
++==========================
++Django 1.2.7 release notes
++==========================
++
++*September 10, 2011*
++
++Welcome to Django 1.2.7!
++
++This is the seventh bugfix/security release in the Django 1.2 series. It
++replaces Django 1.2.6 due to problems with the 1.2.6 release tarball.
++Django 1.2.7 is a recommended upgrade for all users of any Django release in
++the 1.2.X series.
++
++For more information, see the `release advisory`_.
++
++.. _release advisory: https://www.djangoproject.com/weblog/2011/sep/10/127/
+diff --git a/docs/releases/1.3.1.txt b/docs/releases/1.3.1.txt
+new file mode 100644
+index 0000000..4c28916
+--- /dev/null
++++ b/docs/releases/1.3.1.txt
+@@ -0,0 +1,16 @@
++==========================
++Django 1.3.1 release notes
++==========================
++
++*September 9, 2011*
++
++Welcome to Django 1.3.1!
++
++This is the first security release in the Django 1.3 series, fixing several
++security issues in Django 1.3. Django 1.3.1 is a recommended upgrade for
++all users of Django 1.3.
++
++For a full list of issues addressed in this release, see the `security
++advisory`_.
++
++.. _security advisory: https://www.djangoproject.com/weblog/2011/sep/09/security-releases-issued/
+diff --git a/docs/releases/index.txt b/docs/releases/index.txt
+index 8d23c28..40fe5b0 100644
+--- a/docs/releases/index.txt
++++ b/docs/releases/index.txt
+@@ -19,6 +19,7 @@ Final releases
+ .. toctree::
+ :maxdepth: 1
+
++ 1.3.1
+ 1.3
+
+ 1.2 release
+@@ -26,6 +27,8 @@ Final releases
+ .. toctree::
+ :maxdepth: 1
+
++ 1.2.7
++ 1.2.6
+ 1.2.5
+ 1.2.4
+ 1.2.2
+diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
+index 635f18f..5a2608a 100644
+--- a/docs/topics/auth.txt
++++ b/docs/topics/auth.txt
+@@ -1251,16 +1251,19 @@ can or cannot do with Task instances, specific to your application::
+ ...
+ class Meta:
+ permissions = (
+- ("can_view", "Can see available tasks"),
+- ("can_change_status", "Can change the status of tasks"),
+- ("can_close", "Can remove a task by setting its status as closed"),
++ ("view_task", "Can see available tasks"),
++ ("change_task_status", "Can change the status of tasks"),
++ ("close_task", "Can remove a task by setting its status as closed"),
+ )
+
+ The only thing this does is create those extra permissions when you run
+ :djadmin:`manage.py syncdb <syncdb>`. Your code is in charge of checking the
+ value of these permissions when an user is trying to access the functionality
+ provided by the application (viewing tasks, changing the status of tasks,
+-closing tasks.)
++closing tasks.) Continuing the above example, the following checks if a user may
++view tasks::
++
++ user.has_perm('app.view_task')
+
+ API reference
+ -------------
+diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt
+index 8ef4ea2..9b68353 100644
+--- a/docs/topics/cache.txt
++++ b/docs/topics/cache.txt
+@@ -99,8 +99,9 @@ To use Memcached with Django:
+ on your chosen memcached binding)
+
+ * Set :setting:`LOCATION <CACHES-LOCATION>` to ``ip:port`` values,
+- where ``ip`` is the IP address of the Memcached daemon and
+- ``port`` is the port on which Memcached is running.
++ where ``ip`` is the IP address of the Memcached daemon and ``port`` is the
++ port on which Memcached is running, or to a ``unix:path`` value, where
++ ``path`` is the path to a Memcached Unix socket file.
+
+ In this example, Memcached is running on localhost (127.0.0.1) port 11211, using
+ the ``python-memcached`` binding::
+@@ -112,6 +113,16 @@ the ``python-memcached`` binding::
+ }
+ }
+
++In this example, Memcached is available through a local Unix socket file
++:file:`/tmp/memcached.sock` using the ``python-memcached`` binding::
++
++ CACHES = {
++ 'default': {
++ 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
++ 'LOCATION': 'unix:/tmp/memcached.sock',
++ }
++ }
++
+ One excellent feature of Memcached is its ability to share cache over multiple
+ servers. This means you can run Memcached daemons on multiple machines, and the
+ program will treat the group of machines as a *single* cache, without the need
+@@ -526,9 +537,10 @@ you may expect. But once a particular URL (e.g., ``/foo/23/``) has been
+ requested, subsequent requests to that URL will use the cache.
+
+ ``cache_page`` can also take an optional keyword argument, ``cache``,
+-which directs the decorator to use a specific cache alias when caching view
+-results. By default, the ``default`` alias will be used, but you can specify
+-any cache alias you want::
++which directs the decorator to use a specific cache (from your
++:setting:`CACHES` setting) when caching view results. By default, the
++``default`` cache will be used, but you can specify any cache you
++want::
+
+ @cache_page(60 * 15, cache="special_cache")
+ def my_view(request):
+diff --git a/docs/topics/class-based-views.txt b/docs/topics/class-based-views.txt
+index 3831046..4da48ec 100644
+--- a/docs/topics/class-based-views.txt
++++ b/docs/topics/class-based-views.txt
+@@ -380,7 +380,7 @@ Next, we'll write the ``PublisherBookListView`` view itself::
+ class PublisherBookListView(ListView):
+
+ context_object_name = "book_list"
+- template_name = "books/books_by_publisher.html",
++ template_name = "books/books_by_publisher.html"
+
+ def get_queryset(self):
+ publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
+@@ -396,7 +396,7 @@ use it in the template::
+ class PublisherBookListView(ListView):
+
+ context_object_name = "book_list"
+- template_name = "books/books_by_publisher.html",
++ template_name = "books/books_by_publisher.html"
+
+ def get_queryset(self):
+ self.publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
+diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt
+index 0e18205..af76344 100644
+--- a/docs/topics/db/models.txt
++++ b/docs/topics/db/models.txt
+@@ -324,11 +324,10 @@ whatever you want. For example::
+ should work; all are optional.
+
+ For details on accessing backwards-related objects, see the
+- `Following relationships backward example`_.
+-
++ :ref:`Following relationships backward example <backwards-related-objects>`.
++
+ For sample code, see the `Many-to-one relationship model tests`_.
+
+- .. _Following relationships backward example: http://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects
+ .. _Many-to-one relationship model tests: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/many_to_one
+
+ Many-to-many relationships
+diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt
+index fe71736..d9b8b1a 100644
+--- a/docs/topics/db/sql.txt
++++ b/docs/topics/db/sql.txt
+@@ -236,6 +236,30 @@ alias::
+ # Your code here...
+ transaction.commit_unless_managed(using='my_db_alias')
+
++By default, the Python DB API will return results without their field
++names, which means you end up with a ``list`` of values, rather than a
++``dict``. At a small performance cost, you can return results as a
++``dict`` by using something like this::
++
++ def dictfetchall(cursor):
++ "Returns all rows from a cursor as a dict"
++ desc = cursor.description
++ return [
++ dict(zip([col[0] for col in desc], row))
++ for row in cursor.fetchall()
++ ]
++
++Here is an example of the difference between the two::
++
++ >>> cursor.execute("SELECT id, parent_id from test LIMIT 2");
++ >>> cursor.fetchall()
++ ((54360982L, None), (54360880L, None))
++
++ >>> cursor.execute("SELECT id, parent_id from test LIMIT 2");
++ >>> dictfetchall(cursor)
++ [{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}]
++
++
+ .. _transactions-and-raw-sql:
+
+ Transactions and raw SQL
+diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt
+index 07bc5e3..24e000e 100644
+--- a/docs/topics/forms/modelforms.txt
++++ b/docs/topics/forms/modelforms.txt
+@@ -332,13 +332,17 @@ Since the Author model has only 3 fields, 'name', 'title', and
+ .. note::
+
+ If you specify ``fields`` or ``exclude`` when creating a form with
+- ``ModelForm``, then the fields that are not in the resulting form will not
+- be set by the form's ``save()`` method. Django will prevent any attempt to
+- save an incomplete model, so if the model does not allow the missing fields
+- to be empty, and does not provide a default value for the missing fields,
+- any attempt to ``save()`` a ``ModelForm`` with missing fields will fail.
+- To avoid this failure, you must instantiate your model with initial values
+- for the missing, but required fields::
++ ``ModelForm``, then the fields that are not in the resulting form
++ will not be set by the form's ``save()`` method. Also, if you
++ manually add the excluded fields back to the form, they will not
++ be initialized from the model instance.
++
++ Django will prevent any attempt to save an incomplete model, so if
++ the model does not allow the missing fields to be empty, and does
++ not provide a default value for the missing fields, any attempt to
++ ``save()`` a ``ModelForm`` with missing fields will fail. To
++ avoid this failure, you must instantiate your model with initial
++ values for the missing, but required fields::
+
+ author = Author(title='Mr')
+ form = PartialAuthorForm(request.POST, instance=author)
+@@ -633,6 +637,12 @@ database. If a given instance's data didn't change in the bound data, the
+ instance won't be saved to the database and won't be included in the return
+ value (``instances``, in the above example).
+
++When fields are missing from the form (for example because they have
++been excluded), these fields will not be set by the ``save()``
++method. You can find more information about this restriction, which
++also holds for regular ``ModelForms``, in `Using a subset of fields on
++the form`_.
++
+ Pass ``commit=False`` to return the unsaved model instances::
+
+ # don't save to the database
+diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
+index 1caa801..7a0e724 100644
+--- a/docs/topics/http/urls.txt
++++ b/docs/topics/http/urls.txt
+@@ -54,6 +54,10 @@ algorithm the system follows to determine which Python code to execute:
+ :class:`~django.http.HttpRequest` as its first argument and any values
+ captured in the regex as remaining arguments.
+
++ 5. If no regex matches, or if an exception is raised during any
++ point in this process, Django invokes an appropriate
++ error-handling view. See `Error handling`_ below.
++
+ Example
+ =======
+
+@@ -99,10 +103,10 @@ Example requests:
+ * ``/articles/2003`` would not match any of these patterns, because each
+ pattern requires that the URL end with a slash.
+
+- * ``/articles/2003/03/3/`` would match the final pattern. Django would call
+- the function ``news.views.article_detail(request, '2003', '03', '3')``.
++ * ``/articles/2003/03/03/`` would match the final pattern. Django would call
++ the function ``news.views.article_detail(request, '2003', '03', '03')``.
+
+-.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3
++.. _Dive Into Python's explanation: http://diveintopython.net/regular_expressions/street_addresses.html#re.matching.2.3
+
+ Named groups
+ ============
+@@ -123,7 +127,7 @@ Here's the above example URLconf, rewritten to use named groups::
+ (r'^articles/2003/$', 'news.views.special_case_2003'),
+ (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
+ (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
+- (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),
++ (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', 'news.views.article_detail'),
+ )
+
+ This accomplishes exactly the same thing as the previous example, with one
+@@ -134,8 +138,8 @@ arguments rather than positional arguments. For example:
+ ``news.views.month_archive(request, year='2005', month='03')``, instead
+ of ``news.views.month_archive(request, '2005', '03')``.
+
+- * A request to ``/articles/2003/03/3/`` would call the function
+- ``news.views.article_detail(request, year='2003', month='03', day='3')``.
++ * A request to ``/articles/2003/03/03/`` would call the function
++ ``news.views.article_detail(request, year='2003', month='03', day='03')``.
+
+ In practice, this means your URLconfs are slightly more explicit and less prone
+ to argument-order bugs -- and you can reorder the arguments in your views'
+@@ -246,6 +250,31 @@ The ``prefix`` parameter has the same meaning as the first argument to
+ ``patterns()`` and is only relevant when you're passing a string as the
+ ``view`` parameter.
+
++include
++-------
++
++.. function:: include(<module or pattern_list>)
++
++A function that takes a full Python import path to another URLconf module that
++should be "included" in this place.
++
++:func:`include` also accepts as an argument an iterable that returns URL
++patterns.
++
++See `Including other URLconfs`_ below.
++
++Error handling
++==============
++
++When Django can't find a regex matching the requested URL, or when an
++exception is raised, Django will invoke an error-handling view. The
++views to use for these cases are specified by two variables which can
++be set in your root URLconf. Setting these variables in any other
++URLconf will have no effect.
++
++See the documentation on :ref:`customizing error views
++<customizing-error-views>` for more details.
++
+ handler404
+ ----------
+
+@@ -275,19 +304,6 @@ value should suffice.
+ .. versionchanged:: 1.2
+ Previous versions of Django only accepted strings representing import paths.
+
+-include
+--------
+-
+-.. function:: include(<module or pattern_list>)
+-
+-A function that takes a full Python import path to another URLconf module that
+-should be "included" in this place.
+-
+-:func:`include` also accepts as an argument an iterable that returns URL
+-patterns.
+-
+-See `Including other URLconfs`_ below.
+-
+ Notes on capturing text in URLs
+ ===============================
+
+@@ -420,8 +436,8 @@ directly the pattern list as returned by `patterns`_ instead. For example::
+ from django.conf.urls.defaults import *
+
+ extra_patterns = patterns('',
+- url(r'reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'),
+- url(r'charge/$', 'credit.views.charge', name='credit-charge'),
++ url(r'^reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'),
++ url(r'^charge/$', 'credit.views.charge', name='credit-charge'),
+ )
+
+ urlpatterns = patterns('',
+diff --git a/docs/topics/http/views.txt b/docs/topics/http/views.txt
+index 99359ab..83a52cb 100644
+--- a/docs/topics/http/views.txt
++++ b/docs/topics/http/views.txt
+@@ -122,6 +122,8 @@ In order to use the ``Http404`` exception to its fullest, you should create a
+ template that is displayed when a 404 error is raised. This template should be
+ called ``404.html`` and located in the top level of your template tree.
+
++.. _customizing-error-views:
++
+ Customizing error views
+ =======================
+
+diff --git a/docs/topics/i18n/internationalization.txt b/docs/topics/i18n/internationalization.txt
+index 5d50fa7..a83299c 100644
+--- a/docs/topics/i18n/internationalization.txt
++++ b/docs/topics/i18n/internationalization.txt
+@@ -477,7 +477,7 @@ for use within the translation block. Examples::
+
+ You can use multiple expressions inside a single ``blocktrans`` tag::
+
+- {% blocktrans with book_t=book|title and author_t=author|title %}
++ {% blocktrans with book_t=book|title author_t=author|title %}
+ This is {{ book_t }} by {{ author_t }}
+ {% endblocktrans %}
+
+diff --git a/docs/topics/settings.txt b/docs/topics/settings.txt
+index 61ddf8c..bda51f2 100644
+--- a/docs/topics/settings.txt
++++ b/docs/topics/settings.txt
+@@ -39,7 +39,7 @@ The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g.
+ ``mysite.settings``. Note that the settings module should be on the
+ Python `import search path`_.
+
+-.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
++.. _import search path: http://diveintopython.net/getting_to_know_python/everything_is_an_object.html
+
+ The django-admin.py utility
+ ---------------------------
+diff --git a/docs/topics/templates.txt b/docs/topics/templates.txt
+index 83269ae..fc2cd3f 100644
+--- a/docs/topics/templates.txt
++++ b/docs/topics/templates.txt
+@@ -555,6 +555,8 @@ variable that needs escaping. When auto-escaping is on, there's no danger of
+ the ``escape`` filter *double-escaping* data -- the ``escape`` filter does not
+ affect auto-escaped variables.
+
++.. _string-literals-and-automatic-escaping:
++
+ String literals and automatic escaping
+ --------------------------------------
+
+diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt
+index 0a86f0d..8262b57 100644
+--- a/docs/topics/testing.txt
++++ b/docs/topics/testing.txt
+@@ -1586,7 +1586,7 @@ skipUnlessDBFeature
+ Skip the decorated test if the named database feature is *not*
+ supported.
+
+-For example, the following test will not be executed if the database
++For example, the following test will only be executed if the database
+ supports transactions (e.g., it would run under PostgreSQL, but *not*
+ under MySQL with MyISAM tables)::
+
+diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py
+index e585262..4bd5827 100644
+--- a/tests/modeltests/validators/tests.py
++++ b/tests/modeltests/validators/tests.py
+@@ -28,6 +28,9 @@ TEST_DATA = (
+ (validate_email, 'abc', ValidationError),
+ (validate_email, 'a @x.cz', ValidationError),
+ (validate_email, 'something@@somewhere.com', ValidationError),
++ # Quoted-string format (CR not allowed)
++ (validate_email, '"\\\011"@here.com', None),
++ (validate_email, '"\\\012"@here.com', ValidationError),
+
+ (validate_slug, 'slug-ok', None),
+ (validate_slug, 'longer-slug-still-ok', None),
+diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py
+index 2e2932f..6aabfe6 100644
+--- a/tests/regressiontests/httpwrappers/tests.py
++++ b/tests/regressiontests/httpwrappers/tests.py
+@@ -281,3 +281,9 @@ class CookieTests(unittest.TestCase):
+ Test that a single non-standard cookie name doesn't affect all cookies. Ticket #13007.
+ """
+ self.assertTrue('good_cookie' in parse_cookie('good_cookie=yes;bad:cookie=yes').keys())
++
++ def test_repeated_nonstandard_keys(self):
++ """
++ Test that a repeated non-standard name doesn't affect all cookies. Ticket #15852
++ """
++ self.assertTrue('good_cookie' in parse_cookie('a,=b; a,=c; good_cookie=yes').keys())
+diff --git a/tests/regressiontests/utils/http.py b/tests/regressiontests/utils/http.py
+index 83a4a7f..666d04f 100644
+--- a/tests/regressiontests/utils/http.py
++++ b/tests/regressiontests/utils/http.py
+@@ -1,5 +1,7 @@
+ from django.utils import http
+ from django.utils import unittest
++from django.http import HttpResponse, utils
++from django.test import RequestFactory
+
+ class TestUtilsHttp(unittest.TestCase):
+
+@@ -21,3 +23,49 @@ class TestUtilsHttp(unittest.TestCase):
+ self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com'))
+ # Different port
+ self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001'))
++
++ def test_fix_IE_for_vary(self):
++ """
++ Regression for #16632.
++
++ `fix_IE_for_vary` shouldn't crash when there's no Content-Type header.
++ """
++
++ # functions to generate responses
++ def response_with_unsafe_content_type():
++ r = HttpResponse(content_type="text/unsafe")
++ r['Vary'] = 'Cookie'
++ return r
++
++ def no_content_response_with_unsafe_content_type():
++ # 'Content-Type' always defaulted, so delete it
++ r = response_with_unsafe_content_type()
++ del r['Content-Type']
++ return r
++
++ # request with & without IE user agent
++ rf = RequestFactory()
++ request = rf.get('/')
++ ie_request = rf.get('/', HTTP_USER_AGENT='MSIE')
++
++ # not IE, unsafe_content_type
++ response = response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(request, response)
++ self.assertTrue('Vary' in response)
++
++ # IE, unsafe_content_type
++ response = response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(ie_request, response)
++ self.assertFalse('Vary' in response)
++
++ # not IE, no_content
++ response = no_content_response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(request, response)
++ self.assertTrue('Vary' in response)
++
++ # IE, no_content
++ response = no_content_response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(ie_request, response)
++ self.assertFalse('Vary' in response)
++
++
diff --git a/libre/django13/diff-django_branches_releases_1.3.X-from-16771-to-17460.diff b/libre/django13/diff-django_branches_releases_1.3.X-from-16771-to-17460.diff
new file mode 100644
index 000000000..ebbf80993
--- /dev/null
+++ b/libre/django13/diff-django_branches_releases_1.3.X-from-16771-to-17460.diff
@@ -0,0 +1,1575 @@
+Index: django/http/__init__.py
+===================================================================
+--- django/http/__init__.py (revision 16771)
++++ django/http/__init__.py (revision 17460)
+@@ -92,7 +92,7 @@
+ if not _cookie_allows_colon_in_names:
+ def load(self, rawdata, ignore_parse_errors=False):
+ if ignore_parse_errors:
+- self.bad_cookies = []
++ self.bad_cookies = set()
+ self._BaseCookie__set = self._loose_set
+ super(SimpleCookie, self).load(rawdata)
+ if ignore_parse_errors:
+@@ -106,8 +106,8 @@
+ try:
+ self._strict_set(key, real_value, coded_value)
+ except Cookie.CookieError:
+- self.bad_cookies.append(key)
+- dict.__setitem__(self, key, None)
++ self.bad_cookies.add(key)
++ dict.__setitem__(self, key, Cookie.Morsel())
+
+
+ class CompatCookie(SimpleCookie):
+Index: django/http/utils.py
+===================================================================
+--- django/http/utils.py (revision 16771)
++++ django/http/utils.py (revision 17460)
+@@ -76,7 +76,8 @@
+
+ # The first part of the Content-Type field will be the MIME type,
+ # everything after ';', such as character-set, can be ignored.
+- if response['Content-Type'].split(';')[0] not in safe_mime_types:
++ mime_type = response.get('Content-Type', '').partition(';')[0]
++ if mime_type not in safe_mime_types:
+ try:
+ del response['Vary']
+ except KeyError:
+Index: django/db/backends/creation.py
+===================================================================
+--- django/db/backends/creation.py (revision 16771)
++++ django/db/backends/creation.py (revision 17460)
+@@ -374,15 +374,6 @@
+ verbosity=max(verbosity - 1, 0),
+ interactive=False,
+ database=self.connection.alias)
+-
+- # One effect of calling syncdb followed by flush is that the id of the
+- # default site may or may not be 1, depending on how the sequence was
+- # reset. If the sites app is loaded, then we coerce it.
+- from django.db.models import get_model
+- if 'django.contrib.sites' in settings.INSTALLED_APPS:
+- Site = get_model('sites', 'Site')
+- if Site is not None and Site.objects.using(self.connection.alias).count() == 1:
+- Site.objects.using(self.connection.alias).update(id=settings.SITE_ID)
+
+ from django.core.cache import get_cache
+ from django.core.cache.backends.db import BaseDatabaseCache
+Index: django/core/validators.py
+===================================================================
+--- django/core/validators.py (revision 16771)
++++ django/core/validators.py (revision 17460)
+@@ -147,7 +147,8 @@
+
+ email_re = re.compile(
+ r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
+- r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
++ # quoted-string, see also http://tools.ietf.org/html/rfc2822#section-3.2.5
++ r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
+ r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE) # domain
+ validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')
+
+Index: django/core/management/commands/shell.py
+===================================================================
+--- django/core/management/commands/shell.py (revision 16771)
++++ django/core/management/commands/shell.py (revision 17460)
+@@ -13,9 +13,8 @@
+
+ def ipython(self):
+ try:
+- from IPython.frontend.terminal.embed import TerminalInteractiveShell
+- shell = TerminalInteractiveShell()
+- shell.mainloop()
++ from IPython import embed
++ embed()
+ except ImportError:
+ # IPython < 0.11
+ # Explicitly pass an empty list as arguments, because otherwise
+Index: django/contrib/gis/db/models/sql/compiler.py
+===================================================================
+--- django/contrib/gis/db/models/sql/compiler.py (revision 16771)
++++ django/contrib/gis/db/models/sql/compiler.py (revision 17460)
+@@ -1,7 +1,7 @@
+ from itertools import izip
+-from django.db.backends.util import truncate_name
++from django.db.backends.util import truncate_name, typecast_timestamp
+ from django.db.models.sql import compiler
+-from django.db.models.sql.constants import TABLE_NAME
++from django.db.models.sql.constants import TABLE_NAME, MULTI
+ from django.db.models.sql.query import get_proxied_model
+
+ SQLCompiler = compiler.SQLCompiler
+@@ -194,7 +194,7 @@
+ # We resolve the rest of the columns if we're on Oracle or if
+ # the `geo_values` attribute is defined.
+ for value, field in map(None, row[index_start:], fields):
+- values.append(self.query.convert_values(value, field, connection=self.connection))
++ values.append(self.query.convert_values(value, field, self.connection))
+ else:
+ values.extend(row[index_start:])
+ return tuple(values)
+@@ -275,4 +275,24 @@
+ pass
+
+ class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
+- pass
++ """
++ This is overridden for GeoDjango to properly cast date columns, since
++ `GeoQuery.resolve_columns` is used for spatial values.
++ See #14648, #16757.
++ """
++ def results_iter(self):
++ if self.connection.ops.oracle:
++ from django.db.models.fields import DateTimeField
++ fields = [DateTimeField()]
++ else:
++ needs_string_cast = self.connection.features.needs_datetime_string_cast
++
++ offset = len(self.query.extra_select)
++ for rows in self.execute_sql(MULTI):
++ for row in rows:
++ date = row[offset]
++ if self.connection.ops.oracle:
++ date = self.resolve_columns(row, fields)[offset]
++ elif needs_string_cast:
++ date = typecast_timestamp(str(date))
++ yield date
+Index: django/contrib/gis/db/backends/spatialite/compiler.py
+===================================================================
+--- django/contrib/gis/db/backends/spatialite/compiler.py (revision 16771)
++++ django/contrib/gis/db/backends/spatialite/compiler.py (revision 17460)
+@@ -1,32 +0,0 @@
+-from django.db.backends.util import typecast_timestamp
+-from django.db.models.sql import compiler
+-from django.db.models.sql.constants import MULTI
+-from django.contrib.gis.db.models.sql.compiler import GeoSQLCompiler as BaseGeoSQLCompiler
+-
+-SQLCompiler = compiler.SQLCompiler
+-
+-class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler):
+- pass
+-
+-class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLUpdateCompiler(compiler.SQLUpdateCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
+- pass
+-
+-class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
+- """
+- This is overridden for GeoDjango to properly cast date columns, see #16757.
+- """
+- def results_iter(self):
+- offset = len(self.query.extra_select)
+- for rows in self.execute_sql(MULTI):
+- for row in rows:
+- date = typecast_timestamp(str(row[offset]))
+- yield date
+Index: django/contrib/gis/db/backends/spatialite/operations.py
+===================================================================
+--- django/contrib/gis/db/backends/spatialite/operations.py (revision 16771)
++++ django/contrib/gis/db/backends/spatialite/operations.py (revision 17460)
+@@ -48,7 +48,7 @@
+ return (SpatiaLiteDistance(operator),)
+
+ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
+- compiler_module = 'django.contrib.gis.db.backends.spatialite.compiler'
++ compiler_module = 'django.contrib.gis.db.models.sql.compiler'
+ name = 'spatialite'
+ spatialite = True
+ version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
+Index: django/contrib/gis/db/backends/spatialite/creation.py
+===================================================================
+--- django/contrib/gis/db/backends/spatialite/creation.py (revision 16771)
++++ django/contrib/gis/db/backends/spatialite/creation.py (revision 17460)
+@@ -56,14 +56,6 @@
+ interactive=False,
+ database=self.connection.alias)
+
+- # One effect of calling syncdb followed by flush is that the id of the
+- # default site may or may not be 1, depending on how the sequence was
+- # reset. If the sites app is loaded, then we coerce it.
+- from django.db.models import get_model
+- Site = get_model('sites', 'Site')
+- if Site is not None and Site.objects.using(self.connection.alias).count() == 1:
+- Site.objects.using(self.connection.alias).update(id=settings.SITE_ID)
+-
+ from django.core.cache import get_cache
+ from django.core.cache.backends.db import BaseDatabaseCache
+ for cache_alias in settings.CACHES:
+Index: django/contrib/gis/tests/relatedapp/fixtures/initial_data.json.gz
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+Index: django/contrib/gis/tests/relatedapp/tests.py
+===================================================================
+--- django/contrib/gis/tests/relatedapp/tests.py (revision 16771)
++++ django/contrib/gis/tests/relatedapp/tests.py (revision 17460)
+@@ -1,3 +1,4 @@
++from datetime import date
+ from django.test import TestCase
+
+ from django.contrib.gis.geos import GEOSGeometry, Point, MultiPoint
+@@ -281,4 +282,11 @@
+ # evaluated as list generation swallows TypeError in CPython.
+ sql = str(qs.query)
+
++ def test16_annotated_date_queryset(self):
++ "Ensure annotated date querysets work if spatial backend is used. See #14648."
++ birth_years = [dt.year for dt in
++ list(Author.objects.annotate(num_books=Count('books')).dates('dob', 'year'))]
++ birth_years.sort()
++ self.assertEqual([1950, 1974], birth_years)
++
+ # TODO: Related tests for KML, GML, and distance lookups.
+Index: django/contrib/gis/tests/relatedapp/models.py
+===================================================================
+--- django/contrib/gis/tests/relatedapp/models.py (revision 16771)
++++ django/contrib/gis/tests/relatedapp/models.py (revision 17460)
+@@ -36,6 +36,7 @@
+ # These use the GeoManager but do not have any geographic fields.
+ class Author(models.Model):
+ name = models.CharField(max_length=100)
++ dob = models.DateField()
+ objects = models.GeoManager()
+
+ class Article(models.Model):
+Index: django/contrib/sites/management.py
+===================================================================
+--- django/contrib/sites/management.py (revision 16771)
++++ django/contrib/sites/management.py (revision 17460)
+@@ -3,15 +3,34 @@
+ """
+
+ from django.db.models import signals
++from django.db import connections
++from django.db import router
+ from django.contrib.sites.models import Site
+ from django.contrib.sites import models as site_app
++from django.core.management.color import no_style
+
+ def create_default_site(app, created_models, verbosity, db, **kwargs):
+- if Site in created_models:
++ # Only create the default sites in databases where Django created the table
++ if Site in created_models and router.allow_syncdb(db, Site) :
++ # The default settings set SITE_ID = 1, and some tests in Django's test
++ # suite rely on this value. However, if database sequences are reused
++ # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that
++ # the next id will be 1, so we coerce it. See #15573 and #16353. This
++ # can also crop up outside of tests - see #15346.
+ if verbosity >= 2:
+ print "Creating example.com Site object"
+- s = Site(domain="example.com", name="example.com")
+- s.save(using=db)
++ Site(pk=1, domain="example.com", name="example.com").save(using=db)
++
++ # We set an explicit pk instead of relying on auto-incrementation,
++ # so we need to reset the database sequence.
++ sequence_sql = connections[db].ops.sequence_reset_sql(no_style(), [Site])
++ if sequence_sql:
++ if verbosity >= 2:
++ print "Resetting sequence"
++ cursor = connections[db].cursor()
++ for command in sequence_sql:
++ cursor.execute(command)
++
+ Site.objects.clear_cache()
+
+ signals.post_syncdb.connect(create_default_site, sender=site_app)
+Index: django/contrib/sites/tests.py
+===================================================================
+--- django/contrib/sites/tests.py (revision 16771)
++++ django/contrib/sites/tests.py (revision 17460)
+@@ -15,6 +15,12 @@
+ def tearDown(self):
+ Site._meta.installed = self.old_Site_meta_installed
+
++ def test_save_another(self):
++ # Regression for #17415
++ # On some backends the sequence needs reset after save with explicit ID.
++ # Test that there is no sequence collisions by saving another site.
++ Site(domain="example2.com", name="example2.com").save()
++
+ def test_site_manager(self):
+ # Make sure that get_current() does not return a deleted Site object.
+ s = Site.objects.get_current()
+Index: django/contrib/admin/media/css/forms.css
+===================================================================
+--- django/contrib/admin/media/css/forms.css (revision 16771)
++++ django/contrib/admin/media/css/forms.css (revision 17460)
+@@ -352,9 +352,3 @@
+ .empty-form {
+ display: none;
+ }
+-
+-/* IE7 specific bug fixes */
+-
+-.submit-row input {
+- float: right;
+-}
+\ No newline at end of file
+Index: tests/modeltests/validators/tests.py
+===================================================================
+--- tests/modeltests/validators/tests.py (revision 16771)
++++ tests/modeltests/validators/tests.py (revision 17460)
+@@ -28,6 +28,9 @@
+ (validate_email, 'abc', ValidationError),
+ (validate_email, 'a @x.cz', ValidationError),
+ (validate_email, 'something@@somewhere.com', ValidationError),
++ # Quoted-string format (CR not allowed)
++ (validate_email, '"\\\011"@here.com', None),
++ (validate_email, '"\\\012"@here.com', ValidationError),
+
+ (validate_slug, 'slug-ok', None),
+ (validate_slug, 'longer-slug-still-ok', None),
+Index: tests/regressiontests/utils/http.py
+===================================================================
+--- tests/regressiontests/utils/http.py (revision 16771)
++++ tests/regressiontests/utils/http.py (revision 17460)
+@@ -1,5 +1,7 @@
+ from django.utils import http
+ from django.utils import unittest
++from django.http import HttpResponse, utils
++from django.test import RequestFactory
+
+ class TestUtilsHttp(unittest.TestCase):
+
+@@ -21,3 +23,49 @@
+ self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com'))
+ # Different port
+ self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001'))
++
++ def test_fix_IE_for_vary(self):
++ """
++ Regression for #16632.
++
++ `fix_IE_for_vary` shouldn't crash when there's no Content-Type header.
++ """
++
++ # functions to generate responses
++ def response_with_unsafe_content_type():
++ r = HttpResponse(content_type="text/unsafe")
++ r['Vary'] = 'Cookie'
++ return r
++
++ def no_content_response_with_unsafe_content_type():
++ # 'Content-Type' always defaulted, so delete it
++ r = response_with_unsafe_content_type()
++ del r['Content-Type']
++ return r
++
++ # request with & without IE user agent
++ rf = RequestFactory()
++ request = rf.get('/')
++ ie_request = rf.get('/', HTTP_USER_AGENT='MSIE')
++
++ # not IE, unsafe_content_type
++ response = response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(request, response)
++ self.assertTrue('Vary' in response)
++
++ # IE, unsafe_content_type
++ response = response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(ie_request, response)
++ self.assertFalse('Vary' in response)
++
++ # not IE, no_content
++ response = no_content_response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(request, response)
++ self.assertTrue('Vary' in response)
++
++ # IE, no_content
++ response = no_content_response_with_unsafe_content_type()
++ utils.fix_IE_for_vary(ie_request, response)
++ self.assertFalse('Vary' in response)
++
++
+Index: tests/regressiontests/httpwrappers/tests.py
+===================================================================
+--- tests/regressiontests/httpwrappers/tests.py (revision 16771)
++++ tests/regressiontests/httpwrappers/tests.py (revision 17460)
+@@ -281,3 +281,9 @@
+ Test that a single non-standard cookie name doesn't affect all cookies. Ticket #13007.
+ """
+ self.assertTrue('good_cookie' in parse_cookie('good_cookie=yes;bad:cookie=yes').keys())
++
++ def test_repeated_nonstandard_keys(self):
++ """
++ Test that a repeated non-standard name doesn't affect all cookies. Ticket #15852
++ """
++ self.assertTrue('good_cookie' in parse_cookie('a,=b; a,=c; good_cookie=yes').keys())
+Index: docs/index.txt
+===================================================================
+--- docs/index.txt (revision 16771)
++++ docs/index.txt (revision 17460)
+@@ -28,7 +28,7 @@
+ .. _archives of the django-users mailing list: http://groups.google.com/group/django-users/
+ .. _post a question: http://groups.google.com/group/django-users/
+ .. _#django IRC channel: irc://irc.freenode.net/django
+-.. _IRC logs: http://botland.oebfare.com/logger/django/
++.. _IRC logs: http://django-irc-logs.com/
+ .. _ticket tracker: http://code.djangoproject.com/
+
+ First steps
+Index: docs/intro/tutorial01.txt
+===================================================================
+--- docs/intro/tutorial01.txt (revision 16771)
++++ docs/intro/tutorial01.txt (revision 17460)
+@@ -59,7 +59,7 @@
+ can be run as a program. To do this, open Terminal.app and navigate (using
+ the ``cd`` command) to the directory where :doc:`django-admin.py
+ </ref/django-admin>` is installed, then run the command
+- ``chmod +x django-admin.py``.
++ ``sudo chmod +x django-admin.py``.
+
+ .. note::
+
+@@ -692,10 +692,9 @@
+
+ For more information on model relations, see :doc:`Accessing related objects
+ </ref/models/relations>`. For more on how to use double underscores to perform
+-field lookups via the API, see `Field lookups`__. For full details on the
+-database API, see our :doc:`Database API reference </topics/db/queries>`.
++field lookups via the API, see :ref:`Field lookups <field-lookups-intro>`. For
++full details on the database API, see our :doc:`Database API reference
++</topics/db/queries>`.
+
+-__ http://docs.djangoproject.com/en/1.2/topics/db/queries/#field-lookups
+-
+ When you're comfortable with the API, read :doc:`part 2 of this tutorial
+ </intro/tutorial02>` to get Django's automatic admin working.
+Index: docs/intro/tutorial02.txt
+===================================================================
+--- docs/intro/tutorial02.txt (revision 16771)
++++ docs/intro/tutorial02.txt (revision 17460)
+@@ -40,22 +40,22 @@
+
+ .. parsed-literal::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ # Uncomment the next two lines to enable the admin:
+ **from django.contrib import admin**
+ **admin.autodiscover()**
+
+ urlpatterns = patterns('',
+- # Example:
+- # (r'^mysite/', include('mysite.foo.urls')),
++ # Examples:
++ # url(r'^$', 'mysite.views.home', name='home'),
++ # url(r'^mysite/', include('mysite.foo.urls')),
+
+- # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+- # to INSTALLED_APPS to enable admin documentation:
+- # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
++ # Uncomment the admin/doc line below to enable admin documentation:
++ # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ # Uncomment the next line to enable the admin:
+- **(r'^admin/', include(admin.site.urls)),**
++ **url(r'^admin/', include(admin.site.urls)),**
+ )
+
+ (The bold lines are the ones that needed to be uncommented.)
+Index: docs/intro/tutorial03.txt
+===================================================================
+--- docs/intro/tutorial03.txt (revision 16771)
++++ docs/intro/tutorial03.txt (revision 17460)
+@@ -78,17 +78,17 @@
+
+ Time for an example. Edit ``mysite/urls.py`` so it looks like this::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ from django.contrib import admin
+ admin.autodiscover()
+
+ urlpatterns = patterns('',
+- (r'^polls/$', 'polls.views.index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
+- (r'^admin/', include(admin.site.urls)),
++ url(r'^polls/$', 'polls.views.index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
++ url(r'^admin/', include(admin.site.urls)),
+ )
+
+ This is worth a review. When somebody requests a page from your Web site -- say,
+@@ -112,7 +112,7 @@
+ -- unless you have a sick sense of humor, in which case you can do something
+ like this::
+
+- (r'^polls/latest\.php$', 'polls.views.index'),
++ url(r'^polls/latest\.php$', 'polls.views.index'),
+
+ But, don't do that. It's silly.
+
+@@ -357,23 +357,24 @@
+ Write a 404 (page not found) view
+ =================================
+
+-When you raise :exc:`~django.http.Http404` from within a view, Django will load
+-a special view devoted to handling 404 errors. It finds it by looking for the
+-variable ``handler404``, which is a string in Python dotted syntax -- the same
+-format the normal URLconf callbacks use. A 404 view itself has nothing special:
+-It's just a normal view.
++When you raise :exc:`~django.http.Http404` from within a view, Django
++will load a special view devoted to handling 404 errors. It finds it
++by looking for the variable ``handler404`` in your root URLconf (and
++only in your root URLconf; setting ``handler404`` anywhere else will
++have no effect), which is a string in Python dotted syntax -- the same
++format the normal URLconf callbacks use. A 404 view itself has nothing
++special: It's just a normal view.
+
+-You normally won't have to bother with writing 404 views. By default, URLconfs
+-have the following line up top::
++You normally won't have to bother with writing 404 views. If you don't set
++``handler404``, the built-in view :func:`django.views.defaults.page_not_found`
++is used by default. In this case, you still have one obligation: To create a
++``404.html`` template in the root of your template directory. The default 404
++view will use that template for all 404 errors. If :setting:`DEBUG` is set to
++``False`` (in your settings module) and if you didn't create a ``404.html``
++file, an ``Http500`` is raised instead. So remember to create a ``404.html``.
+
+- from django.conf.urls.defaults import *
++A couple more things to note about 404 views:
+
+-That takes care of setting ``handler404`` in the current module. As you can see
+-in ``django/conf/urls/defaults.py``, ``handler404`` is set to
+-:func:`django.views.defaults.page_not_found` by default.
+-
+-Four more things to note about 404 views:
+-
+ * If :setting:`DEBUG` is set to ``True`` (in your settings module) then your
+ 404 view will never be used (and thus the ``404.html`` template will never
+ be rendered) because the traceback will be displayed instead.
+@@ -381,21 +382,12 @@
+ * The 404 view is also called if Django doesn't find a match after checking
+ every regular expression in the URLconf.
+
+- * If you don't define your own 404 view -- and simply use the default, which
+- is recommended -- you still have one obligation: To create a ``404.html``
+- template in the root of your template directory. The default 404 view will
+- use that template for all 404 errors.
+-
+- * If :setting:`DEBUG` is set to ``False`` (in your settings module) and if
+- you didn't create a ``404.html`` file, an ``Http500`` is raised instead.
+- So remember to create a ``404.html``.
+-
+ Write a 500 (server error) view
+ ===============================
+
+-Similarly, URLconfs may define a ``handler500``, which points to a view to call
+-in case of server errors. Server errors happen when you have runtime errors in
+-view code.
++Similarly, your root URLconf may define a ``handler500``, which points
++to a view to call in case of server errors. Server errors happen when
++you have runtime errors in view code.
+
+ Use the template system
+ =======================
+@@ -432,10 +424,10 @@
+ the URLconf, you may notice there's a fair bit of redundancy in it::
+
+ urlpatterns = patterns('',
+- (r'^polls/$', 'polls.views.index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
++ url(r'^polls/$', 'polls.views.index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
+ )
+
+ Namely, ``polls.views`` is in every callback.
+@@ -445,10 +437,10 @@
+ first argument to :func:`~django.conf.urls.defaults.patterns`, like so::
+
+ urlpatterns = patterns('polls.views',
+- (r'^polls/$', 'index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^polls/$', 'index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ This is functionally identical to the previous formatting. It's just a bit
+@@ -459,20 +451,20 @@
+ :func:`~django.conf.urls.defaults.patterns`. Your full ``mysite/urls.py`` might
+ now look like this::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ from django.contrib import admin
+ admin.autodiscover()
+
+ urlpatterns = patterns('polls.views',
+- (r'^polls/$', 'index'),
+- (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
+- (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^polls/$', 'index'),
++ url(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ urlpatterns += patterns('',
+- (r'^admin/', include(admin.site.urls)),
++ url(r'^admin/', include(admin.site.urls)),
+ )
+
+ Decoupling the URLconfs
+@@ -502,8 +494,8 @@
+ admin.autodiscover()
+
+ urlpatterns = patterns('',
+- (r'^polls/', include('polls.urls')),
+- (r'^admin/', include(admin.site.urls)),
++ url(r'^polls/', include('polls.urls')),
++ url(r'^admin/', include(admin.site.urls)),
+ )
+
+ :func:`~django.conf.urls.defaults.include` simply references another URLconf.
+@@ -526,13 +518,13 @@
+ lines registering the admin site. Your ``polls/urls.py`` file should now look like
+ this::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ urlpatterns = patterns('polls.views',
+- (r'^$', 'index'),
+- (r'^(?P<poll_id>\d+)/$', 'detail'),
+- (r'^(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^$', 'index'),
++ url(r'^(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ The idea behind :func:`~django.conf.urls.defaults.include` and URLconf
+Index: docs/intro/index.txt
+===================================================================
+--- docs/intro/index.txt (revision 16771)
++++ docs/intro/index.txt (revision 17460)
+@@ -31,6 +31,6 @@
+
+ .. _python: http://python.org/
+ .. _list of Python resources for non-programmers: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers
+- .. _dive into python: http://diveintopython.org/
++ .. _dive into python: http://diveintopython.net/
+ .. _dead-tree version: http://www.amazon.com/exec/obidos/ASIN/1590593561/ref=nosim/jacobian20
+ .. _books about Python: http://wiki.python.org/moin/PythonBooks
+\ No newline at end of file
+Index: docs/intro/tutorial04.txt
+===================================================================
+--- docs/intro/tutorial04.txt (revision 16771)
++++ docs/intro/tutorial04.txt (revision 17460)
+@@ -218,13 +218,13 @@
+ First, open the ``polls/urls.py`` URLconf. It looks like this, according to the
+ tutorial so far::
+
+- from django.conf.urls.defaults import *
++ from django.conf.urls.defaults import patterns, include, url
+
+ urlpatterns = patterns('polls.views',
+- (r'^$', 'index'),
+- (r'^(?P<poll_id>\d+)/$', 'detail'),
+- (r'^(?P<poll_id>\d+)/results/$', 'results'),
+- (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
++ url(r'^$', 'index'),
++ url(r'^(?P<poll_id>\d+)/$', 'detail'),
++ url(r'^(?P<poll_id>\d+)/results/$', 'results'),
++ url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
+ )
+
+ Change it like so::
+@@ -234,12 +234,12 @@
+ from polls.models import Poll
+
+ urlpatterns = patterns('',
+- (r'^$',
++ url(r'^$',
+ ListView.as_view(
+ queryset=Poll.objects.order_by('-pub_date')[:5],
+ context_object_name='latest_poll_list',
+ template_name='polls/index.html')),
+- (r'^(?P<pk>\d+)/$',
++ url(r'^(?P<pk>\d+)/$',
+ DetailView.as_view(
+ model=Poll,
+ template_name='polls/detail.html')),
+@@ -248,7 +248,7 @@
+ model=Poll,
+ template_name='polls/results.html'),
+ name='poll_results'),
+- (r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
++ url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
+ )
+
+ We're using two generic views here:
+Index: docs/internals/release-process.txt
+===================================================================
+--- docs/internals/release-process.txt (revision 16771)
++++ docs/internals/release-process.txt (revision 17460)
+@@ -99,6 +99,13 @@
+ * Security fixes will be applied to the current trunk and the previous two
+ minor releases.
+
++* Documentation fixes will generally be more freely backported to the last
++ release branch (at the discretion of the committer), and don't need to meet
++ the "critical fixes only" bar as it's highly advantageous to have the docs
++ for the last release be up-to-date and correct, and the downside of
++ backporting (risk of introducing regressions) is much less of a concern
++ with doc fixes.
++
+ As a concrete example, consider a moment in time halfway between the release of
+ Django 1.3 and 1.4. At this point in time:
+
+@@ -111,6 +118,9 @@
+ ``1.2.X`` branch. Security fixes will trigger the release of ``1.3.1``,
+ ``1.2.1``, etc.
+
++* Documentation fixes will be applied to trunk, and if easily backported, to
++ the ``1.3.X`` branch.
++
+ .. _release-process:
+
+ Release process
+Index: docs/internals/deprecation.txt
+===================================================================
+--- docs/internals/deprecation.txt (revision 16771)
++++ docs/internals/deprecation.txt (revision 17460)
+@@ -177,6 +177,12 @@
+ required to end with a trailing slash to ensure there is a consistent
+ way to combine paths in templates.
+
++ * Translations located under the so-called *project path* will be
++ ignored during the translation building process performed at runtime.
++ The :setting:`LOCALE_PATHS` setting can be used for the same task by
++ including the filesystem path to a ``locale`` directory containing
++ non-app-specific translations in its value.
++
+ * 2.0
+ * ``django.views.defaults.shortcut()``. This function has been moved
+ to ``django.contrib.contenttypes.views.shortcut()`` as part of the
+Index: docs/howto/deployment/modpython.txt
+===================================================================
+--- docs/howto/deployment/modpython.txt (revision 16771)
++++ docs/howto/deployment/modpython.txt (revision 17460)
+@@ -293,11 +293,14 @@
+ arrangement. You're responsible for setting up Apache, or whichever media
+ server you're using, to serve the admin files.
+
+-The admin files live in (:file:`django/contrib/admin/static/admin`) of the
++The admin files live in (:file:`django/contrib/admin/media/admin`) of the
+ Django distribution.
+
+-We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle
+-the admin files, but here are two other approaches:
++We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle the
++admin files (this means using the :djadmin:`collectstatic` management command
++to collect the static files in :setting:`STATIC_ROOT`, and then configuring
++your webserver to serve :setting:`STATIC_ROOT` at :setting:`STATIC_URL`), but
++here are two other approaches:
+
+ 1. Create a symbolic link to the admin static files from within your
+ document root.
+Index: docs/howto/deployment/modwsgi.txt
+===================================================================
+--- docs/howto/deployment/modwsgi.txt (revision 16771)
++++ docs/howto/deployment/modwsgi.txt (revision 17460)
+@@ -127,11 +127,14 @@
+ arrangement. You're responsible for setting up Apache, or whichever media
+ server you're using, to serve the admin files.
+
+-The admin files live in (:file:`django/contrib/admin/static/admin`) of the
++The admin files live in (:file:`django/contrib/admin/media/admin`) of the
+ Django distribution.
+
+-We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle
+-the admin files, but here are two other approaches:
++We **strongly** recommend using :mod:`django.contrib.staticfiles` to handle the
++admin files (this means using the :djadmin:`collectstatic` management command
++to collect the static files in :setting:`STATIC_ROOT`, and then configuring
++your webserver to serve :setting:`STATIC_ROOT` at :setting:`STATIC_URL`), but
++here are two other approaches:
+
+ 1. Create a symbolic link to the admin static files from within your
+ document root.
+Index: docs/topics/auth.txt
+===================================================================
+--- docs/topics/auth.txt (revision 16771)
++++ docs/topics/auth.txt (revision 17460)
+@@ -1251,17 +1251,20 @@
+ ...
+ class Meta:
+ permissions = (
+- ("can_view", "Can see available tasks"),
+- ("can_change_status", "Can change the status of tasks"),
+- ("can_close", "Can remove a task by setting its status as closed"),
++ ("view_task", "Can see available tasks"),
++ ("change_task_status", "Can change the status of tasks"),
++ ("close_task", "Can remove a task by setting its status as closed"),
+ )
+
+ The only thing this does is create those extra permissions when you run
+ :djadmin:`manage.py syncdb <syncdb>`. Your code is in charge of checking the
+ value of these permissions when an user is trying to access the functionality
+ provided by the application (viewing tasks, changing the status of tasks,
+-closing tasks.)
++closing tasks.) Continuing the above example, the following checks if a user may
++view tasks::
+
++ user.has_perm('app.view_task')
++
+ API reference
+ -------------
+
+Index: docs/topics/http/urls.txt
+===================================================================
+--- docs/topics/http/urls.txt (revision 16771)
++++ docs/topics/http/urls.txt (revision 17460)
+@@ -54,6 +54,10 @@
+ :class:`~django.http.HttpRequest` as its first argument and any values
+ captured in the regex as remaining arguments.
+
++ 5. If no regex matches, or if an exception is raised during any
++ point in this process, Django invokes an appropriate
++ error-handling view. See `Error handling`_ below.
++
+ Example
+ =======
+
+@@ -99,10 +103,10 @@
+ * ``/articles/2003`` would not match any of these patterns, because each
+ pattern requires that the URL end with a slash.
+
+- * ``/articles/2003/03/3/`` would match the final pattern. Django would call
+- the function ``news.views.article_detail(request, '2003', '03', '3')``.
++ * ``/articles/2003/03/03/`` would match the final pattern. Django would call
++ the function ``news.views.article_detail(request, '2003', '03', '03')``.
+
+-.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3
++.. _Dive Into Python's explanation: http://diveintopython.net/regular_expressions/street_addresses.html#re.matching.2.3
+
+ Named groups
+ ============
+@@ -123,7 +127,7 @@
+ (r'^articles/2003/$', 'news.views.special_case_2003'),
+ (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
+ (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
+- (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),
++ (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', 'news.views.article_detail'),
+ )
+
+ This accomplishes exactly the same thing as the previous example, with one
+@@ -134,8 +138,8 @@
+ ``news.views.month_archive(request, year='2005', month='03')``, instead
+ of ``news.views.month_archive(request, '2005', '03')``.
+
+- * A request to ``/articles/2003/03/3/`` would call the function
+- ``news.views.article_detail(request, year='2003', month='03', day='3')``.
++ * A request to ``/articles/2003/03/03/`` would call the function
++ ``news.views.article_detail(request, year='2003', month='03', day='03')``.
+
+ In practice, this means your URLconfs are slightly more explicit and less prone
+ to argument-order bugs -- and you can reorder the arguments in your views'
+@@ -246,6 +250,31 @@
+ ``patterns()`` and is only relevant when you're passing a string as the
+ ``view`` parameter.
+
++include
++-------
++
++.. function:: include(<module or pattern_list>)
++
++A function that takes a full Python import path to another URLconf module that
++should be "included" in this place.
++
++:func:`include` also accepts as an argument an iterable that returns URL
++patterns.
++
++See `Including other URLconfs`_ below.
++
++Error handling
++==============
++
++When Django can't find a regex matching the requested URL, or when an
++exception is raised, Django will invoke an error-handling view. The
++views to use for these cases are specified by two variables which can
++be set in your root URLconf. Setting these variables in any other
++URLconf will have no effect.
++
++See the documentation on :ref:`customizing error views
++<customizing-error-views>` for more details.
++
+ handler404
+ ----------
+
+@@ -275,19 +304,6 @@
+ .. versionchanged:: 1.2
+ Previous versions of Django only accepted strings representing import paths.
+
+-include
+--------
+-
+-.. function:: include(<module or pattern_list>)
+-
+-A function that takes a full Python import path to another URLconf module that
+-should be "included" in this place.
+-
+-:func:`include` also accepts as an argument an iterable that returns URL
+-patterns.
+-
+-See `Including other URLconfs`_ below.
+-
+ Notes on capturing text in URLs
+ ===============================
+
+@@ -420,8 +436,8 @@
+ from django.conf.urls.defaults import *
+
+ extra_patterns = patterns('',
+- url(r'reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'),
+- url(r'charge/$', 'credit.views.charge', name='credit-charge'),
++ url(r'^reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'),
++ url(r'^charge/$', 'credit.views.charge', name='credit-charge'),
+ )
+
+ urlpatterns = patterns('',
+Index: docs/topics/http/views.txt
+===================================================================
+--- docs/topics/http/views.txt (revision 16771)
++++ docs/topics/http/views.txt (revision 17460)
+@@ -122,6 +122,8 @@
+ template that is displayed when a 404 error is raised. This template should be
+ called ``404.html`` and located in the top level of your template tree.
+
++.. _customizing-error-views:
++
+ Customizing error views
+ =======================
+
+Index: docs/topics/i18n/internationalization.txt
+===================================================================
+--- docs/topics/i18n/internationalization.txt (revision 16771)
++++ docs/topics/i18n/internationalization.txt (revision 17460)
+@@ -477,7 +477,7 @@
+
+ You can use multiple expressions inside a single ``blocktrans`` tag::
+
+- {% blocktrans with book_t=book|title and author_t=author|title %}
++ {% blocktrans with book_t=book|title author_t=author|title %}
+ This is {{ book_t }} by {{ author_t }}
+ {% endblocktrans %}
+
+Index: docs/topics/cache.txt
+===================================================================
+--- docs/topics/cache.txt (revision 16771)
++++ docs/topics/cache.txt (revision 17460)
+@@ -99,8 +99,9 @@
+ on your chosen memcached binding)
+
+ * Set :setting:`LOCATION <CACHES-LOCATION>` to ``ip:port`` values,
+- where ``ip`` is the IP address of the Memcached daemon and
+- ``port`` is the port on which Memcached is running.
++ where ``ip`` is the IP address of the Memcached daemon and ``port`` is the
++ port on which Memcached is running, or to a ``unix:path`` value, where
++ ``path`` is the path to a Memcached Unix socket file.
+
+ In this example, Memcached is running on localhost (127.0.0.1) port 11211, using
+ the ``python-memcached`` binding::
+@@ -112,6 +113,16 @@
+ }
+ }
+
++In this example, Memcached is available through a local Unix socket file
++:file:`/tmp/memcached.sock` using the ``python-memcached`` binding::
++
++ CACHES = {
++ 'default': {
++ 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
++ 'LOCATION': 'unix:/tmp/memcached.sock',
++ }
++ }
++
+ One excellent feature of Memcached is its ability to share cache over multiple
+ servers. This means you can run Memcached daemons on multiple machines, and the
+ program will treat the group of machines as a *single* cache, without the need
+@@ -526,9 +537,10 @@
+ requested, subsequent requests to that URL will use the cache.
+
+ ``cache_page`` can also take an optional keyword argument, ``cache``,
+-which directs the decorator to use a specific cache alias when caching view
+-results. By default, the ``default`` alias will be used, but you can specify
+-any cache alias you want::
++which directs the decorator to use a specific cache (from your
++:setting:`CACHES` setting) when caching view results. By default, the
++``default`` cache will be used, but you can specify any cache you
++want::
+
+ @cache_page(60 * 15, cache="special_cache")
+ def my_view(request):
+Index: docs/topics/db/models.txt
+===================================================================
+--- docs/topics/db/models.txt (revision 16771)
++++ docs/topics/db/models.txt (revision 17460)
+@@ -324,11 +324,10 @@
+ should work; all are optional.
+
+ For details on accessing backwards-related objects, see the
+- `Following relationships backward example`_.
+-
++ :ref:`Following relationships backward example <backwards-related-objects>`.
++
+ For sample code, see the `Many-to-one relationship model tests`_.
+
+- .. _Following relationships backward example: http://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects
+ .. _Many-to-one relationship model tests: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/many_to_one
+
+ Many-to-many relationships
+Index: docs/topics/db/sql.txt
+===================================================================
+--- docs/topics/db/sql.txt (revision 16771)
++++ docs/topics/db/sql.txt (revision 17460)
+@@ -236,6 +236,30 @@
+ # Your code here...
+ transaction.commit_unless_managed(using='my_db_alias')
+
++By default, the Python DB API will return results without their field
++names, which means you end up with a ``list`` of values, rather than a
++``dict``. At a small performance cost, you can return results as a
++``dict`` by using something like this::
++
++ def dictfetchall(cursor):
++ "Returns all rows from a cursor as a dict"
++ desc = cursor.description
++ return [
++ dict(zip([col[0] for col in desc], row))
++ for row in cursor.fetchall()
++ ]
++
++Here is an example of the difference between the two::
++
++ >>> cursor.execute("SELECT id, parent_id from test LIMIT 2");
++ >>> cursor.fetchall()
++ ((54360982L, None), (54360880L, None))
++
++ >>> cursor.execute("SELECT id, parent_id from test LIMIT 2");
++ >>> dictfetchall(cursor)
++ [{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}]
++
++
+ .. _transactions-and-raw-sql:
+
+ Transactions and raw SQL
+Index: docs/topics/forms/modelforms.txt
+===================================================================
+--- docs/topics/forms/modelforms.txt (revision 16771)
++++ docs/topics/forms/modelforms.txt (revision 17460)
+@@ -332,14 +332,18 @@
+ .. note::
+
+ If you specify ``fields`` or ``exclude`` when creating a form with
+- ``ModelForm``, then the fields that are not in the resulting form will not
+- be set by the form's ``save()`` method. Django will prevent any attempt to
+- save an incomplete model, so if the model does not allow the missing fields
+- to be empty, and does not provide a default value for the missing fields,
+- any attempt to ``save()`` a ``ModelForm`` with missing fields will fail.
+- To avoid this failure, you must instantiate your model with initial values
+- for the missing, but required fields::
++ ``ModelForm``, then the fields that are not in the resulting form
++ will not be set by the form's ``save()`` method. Also, if you
++ manually add the excluded fields back to the form, they will not
++ be initialized from the model instance.
+
++ Django will prevent any attempt to save an incomplete model, so if
++ the model does not allow the missing fields to be empty, and does
++ not provide a default value for the missing fields, any attempt to
++ ``save()`` a ``ModelForm`` with missing fields will fail. To
++ avoid this failure, you must instantiate your model with initial
++ values for the missing, but required fields::
++
+ author = Author(title='Mr')
+ form = PartialAuthorForm(request.POST, instance=author)
+ form.save()
+@@ -633,6 +637,12 @@
+ instance won't be saved to the database and won't be included in the return
+ value (``instances``, in the above example).
+
++When fields are missing from the form (for example because they have
++been excluded), these fields will not be set by the ``save()``
++method. You can find more information about this restriction, which
++also holds for regular ``ModelForms``, in `Using a subset of fields on
++the form`_.
++
+ Pass ``commit=False`` to return the unsaved model instances::
+
+ # don't save to the database
+Index: docs/topics/class-based-views.txt
+===================================================================
+--- docs/topics/class-based-views.txt (revision 16771)
++++ docs/topics/class-based-views.txt (revision 17460)
+@@ -380,7 +380,7 @@
+ class PublisherBookListView(ListView):
+
+ context_object_name = "book_list"
+- template_name = "books/books_by_publisher.html",
++ template_name = "books/books_by_publisher.html"
+
+ def get_queryset(self):
+ publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
+@@ -396,7 +396,7 @@
+ class PublisherBookListView(ListView):
+
+ context_object_name = "book_list"
+- template_name = "books/books_by_publisher.html",
++ template_name = "books/books_by_publisher.html"
+
+ def get_queryset(self):
+ self.publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
+Index: docs/topics/testing.txt
+===================================================================
+--- docs/topics/testing.txt (revision 16771)
++++ docs/topics/testing.txt (revision 17460)
+@@ -1586,7 +1586,7 @@
+ Skip the decorated test if the named database feature is *not*
+ supported.
+
+-For example, the following test will not be executed if the database
++For example, the following test will only be executed if the database
+ supports transactions (e.g., it would run under PostgreSQL, but *not*
+ under MySQL with MyISAM tables)::
+
+Index: docs/topics/templates.txt
+===================================================================
+--- docs/topics/templates.txt (revision 16771)
++++ docs/topics/templates.txt (revision 17460)
+@@ -555,6 +555,8 @@
+ the ``escape`` filter *double-escaping* data -- the ``escape`` filter does not
+ affect auto-escaped variables.
+
++.. _string-literals-and-automatic-escaping:
++
+ String literals and automatic escaping
+ --------------------------------------
+
+Index: docs/topics/settings.txt
+===================================================================
+--- docs/topics/settings.txt (revision 16771)
++++ docs/topics/settings.txt (revision 17460)
+@@ -39,7 +39,7 @@
+ ``mysite.settings``. Note that the settings module should be on the
+ Python `import search path`_.
+
+-.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
++.. _import search path: http://diveintopython.net/getting_to_know_python/everything_is_an_object.html
+
+ The django-admin.py utility
+ ---------------------------
+Index: docs/releases/1.2.6.txt
+===================================================================
+--- docs/releases/1.2.6.txt (revision 0)
++++ docs/releases/1.2.6.txt (revision 17460)
+@@ -0,0 +1,16 @@
++==========================
++Django 1.2.6 release notes
++==========================
++
++*September 9, 2011*
++
++Welcome to Django 1.2.6!
++
++This is the sixth bugfix/security release in the Django 1.2 series, fixing
++several security issues present in Django 1.2.5. Django 1.2.6 is a
++recommended upgrade for all users of any Django release in the 1.2.X series.
++
++For a full list of issues addressed in this release, see the `security
++advisory`_.
++
++.. _security advisory: https://www.djangoproject.com/weblog/2011/sep/09/security-releases-issued/
+Index: docs/releases/1.2.7.txt
+===================================================================
+--- docs/releases/1.2.7.txt (revision 0)
++++ docs/releases/1.2.7.txt (revision 17460)
+@@ -0,0 +1,16 @@
++==========================
++Django 1.2.7 release notes
++==========================
++
++*September 10, 2011*
++
++Welcome to Django 1.2.7!
++
++This is the seventh bugfix/security release in the Django 1.2 series. It
++replaces Django 1.2.6 due to problems with the 1.2.6 release tarball.
++Django 1.2.7 is a recommended upgrade for all users of any Django release in
++the 1.2.X series.
++
++For more information, see the `release advisory`_.
++
++.. _release advisory: https://www.djangoproject.com/weblog/2011/sep/10/127/
+Index: docs/releases/index.txt
+===================================================================
+--- docs/releases/index.txt (revision 16771)
++++ docs/releases/index.txt (revision 17460)
+@@ -19,6 +19,7 @@
+ .. toctree::
+ :maxdepth: 1
+
++ 1.3.1
+ 1.3
+
+ 1.2 release
+@@ -26,6 +27,8 @@
+ .. toctree::
+ :maxdepth: 1
+
++ 1.2.7
++ 1.2.6
+ 1.2.5
+ 1.2.4
+ 1.2.2
+Index: docs/releases/0.95.txt
+===================================================================
+--- docs/releases/0.95.txt (revision 16771)
++++ docs/releases/0.95.txt (revision 17460)
+@@ -92,15 +92,15 @@
+ easy checklist_ for reference when undertaking the porting operation.
+
+ .. _Removing The Magic: http://code.djangoproject.com/wiki/RemovingTheMagic
+-.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet1
++.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet
+
+ Problem reports and getting help
+ ================================
+
+-Need help resolving a problem with Django? The documentation in the distribution
+-is also available online_ at the `Django Web site`_. The :doc:`FAQ </faq/index>`
+-document is especially recommended, as it contains a number of issues that come
+-up time and again.
++Need help resolving a problem with Django? The documentation in the
++distribution is also available :doc:`online </index>` at the `Django Web
++site`_. The :doc:`FAQ </faq/index>` document is especially recommended, as it
++contains a number of issues that come up time and again.
+
+ For more personalized help, the `django-users`_ mailing list is a very active
+ list, with more than 2,000 subscribers who can help you solve any sort of
+@@ -113,7 +113,6 @@
+ Django users and developers from around the world. Friendly people are usually
+ available at any hour of the day -- to help, or just to chat.
+
+-.. _online: http://www.djangoproject.com/documentation/0.95/
+ .. _Django Web site: http://www.djangoproject.com/
+ .. _django-users: http://groups.google.com/group/django-users
+
+Index: docs/releases/0.96.txt
+===================================================================
+--- docs/releases/0.96.txt (revision 16771)
++++ docs/releases/0.96.txt (revision 17460)
+@@ -50,12 +50,10 @@
+ maintained, and it will be removed in a future release of Django.
+
+ Also, note that some features, like the new :setting:`DATABASE_OPTIONS`
+-setting (see the `databases documentation`_ for details), are only
+-available on the "mysql" backend, and will not be made available for
++setting (see the :doc:`databases documentation </ref/databases>` for details),
++are only available on the "mysql" backend, and will not be made available for
+ "mysql_old".
+
+-.. _databases documentation: http://www.djangoproject.com/documentation/0.96/databases/
+-
+ Database constraint names changed
+ ---------------------------------
+
+@@ -164,11 +162,9 @@
+ for most common cases. We recommend that anyone new to form handling skip the
+ old forms system and start with the new.
+
+-For more information about ``django.newforms``, read the `newforms
+-documentation`_.
++For more information about ``django.newforms``, read the :doc:`newforms
++documentation </topics/forms/index>`.
+
+-.. _newforms documentation: http://www.djangoproject.com/documentation/0.96/newforms/
+-
+ URLconf improvements
+ --------------------
+
+@@ -216,20 +212,16 @@
+ ------------------
+
+ Django now includes a test framework so you can start transmuting fear into
+-boredom (with apologies to Kent Beck). You can write tests based on doctest_
+-or unittest_ and test your views with a simple test client.
++boredom (with apologies to Kent Beck). You can write tests based on
++:mod:`doctest` or :mod:`unittest` and test your views with a simple test client.
+
+ There is also new support for "fixtures" -- initial data, stored in any of the
+-supported `serialization formats`_, that will be loaded into your database at the
+-start of your tests. This makes testing with real data much easier.
++supported :doc:`serialization formats </topics/serialization>`, that will be
++loaded into your database at the start of your tests. This makes testing with
++real data much easier.
+
+-See `the testing documentation`_ for the full details.
++See :doc:`the testing documentation </topics/testing>` for the full details.
+
+-.. _doctest: http://docs.python.org/library/doctest.html
+-.. _unittest: http://docs.python.org/library/unittest.html
+-.. _the testing documentation: http://www.djangoproject.com/documentation/0.96/testing/
+-.. _serialization formats: http://www.djangoproject.com/documentation/0.96/serialization/
+-
+ Improvements to the admin interface
+ -----------------------------------
+
+Index: docs/releases/1.0.1.txt
+===================================================================
+--- docs/releases/1.0.1.txt (revision 16771)
++++ docs/releases/1.0.1.txt (revision 17460)
+@@ -6,10 +6,10 @@
+
+ This is the first "bugfix" release in the Django 1.0 series, improving
+ the stability and performance of the Django 1.0 codebase. As such,
+-Django 1.0.1 contains no new features (and, pursuant to `our
+-compatibility policy`_, maintains backwards compatibility with Django
+-1.0), but does contain a number of fixes and other
+-improvements. Django 1.0.1 is a recommended upgrade for any
++Django 1.0.1 contains no new features (and, pursuant to :doc:`our
++compatibility policy </misc/api-stability/>`, maintains backwards
++compatibility with Django 1.0), but does contain a number of fixes
++and other improvements. Django 1.0.1 is a recommended upgrade for any
+ development or deployment currently using or targeting Django 1.0.
+
+
+@@ -46,8 +46,9 @@
+
+ * A fix to the application of autoescaping for literal strings passed
+ to the ``join`` template filter. Previously, literal strings passed
+- to ``join`` were automatically escaped, contrary to `the documented
+- behavior for autoescaping and literal strings`_. Literal strings
++ to ``join`` were automatically escaped, contrary to :ref:`the
++ documented behavior for autoescaping and literal strings
++ <string-literals-and-automatic-escaping>`. Literal strings
+ passed to ``join`` are no longer automatically escaped, meaning you
+ must now manually escape them; this is an incompatibility if you
+ were relying on this bug, but not if you were relying on escaping
+@@ -60,6 +61,4 @@
+ documentation, including both corrections to existing documents and
+ expanded and new documentation.
+
+-.. _our compatibility policy: http://docs.djangoproject.com/en/dev/misc/api-stability/
+ .. _the Subversion log of the 1.0.X branch: http://code.djangoproject.com/log/django/branches/releases/1.0.X
+-.. _the documented behavior for autoescaping and literal strings: http://docs.djangoproject.com/en/dev/topics/templates/#string-literals-and-automatic-escaping
+Index: docs/releases/1.3.1.txt
+===================================================================
+--- docs/releases/1.3.1.txt (revision 0)
++++ docs/releases/1.3.1.txt (revision 17460)
+@@ -0,0 +1,16 @@
++==========================
++Django 1.3.1 release notes
++==========================
++
++*September 9, 2011*
++
++Welcome to Django 1.3.1!
++
++This is the first security release in the Django 1.3 series, fixing several
++security issues in Django 1.3. Django 1.3.1 is a recommended upgrade for
++all users of Django 1.3.
++
++For a full list of issues addressed in this release, see the `security
++advisory`_.
++
++.. _security advisory: https://www.djangoproject.com/weblog/2011/sep/09/security-releases-issued/
+Index: docs/ref/models/instances.txt
+===================================================================
+--- docs/ref/models/instances.txt (revision 16771)
++++ docs/ref/models/instances.txt (revision 17460)
+@@ -470,7 +470,7 @@
+
+ Similarly, if you had a URLconf entry that looked like::
+
+- (r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', archive_view)
++ (r'/archive/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', archive_view)
+
+ ...you could reference this using ``permalink()`` as follows::
+
+@@ -478,8 +478,8 @@
+ def get_absolute_url(self):
+ return ('archive_view', (), {
+ 'year': self.created.year,
+- 'month': self.created.month,
+- 'day': self.created.day})
++ 'month': self.created.strftime('%m'),
++ 'day': self.created.strftime('%d')})
+
+ Notice that we specify an empty sequence for the second parameter in this case,
+ because we only want to pass keyword parameters, not positional ones.
+Index: docs/ref/models/options.txt
+===================================================================
+--- docs/ref/models/options.txt (revision 16771)
++++ docs/ref/models/options.txt (revision 17460)
+@@ -166,6 +166,13 @@
+ >>> answer.get_previous_in_order()
+ <Answer: 1>
+
++.. admonition:: Changing order_with_respect_to
++
++ ``order_with_respect_to`` adds an additional field/database column
++ named ``_order``, so be sure to handle that as you would any other
++ change to your models if you add or change ``order_with_respect_to``
++ after your initial :djadmin:`syncdb`.
++
+ ``ordering``
+ ------------
+
+@@ -238,6 +245,12 @@
+
+ unique_together = ("driver", "restaurant")
+
++ A :class:`~django.db.models.ManyToManyField` cannot be included in
++ unique_together (it's not even clear what that would mean). If you
++ need to validate uniqueness related to a
++ :class:`~django.db.models.ManyToManyField`, look at signals or
++ using an explicit :attr:`through <ManyToManyField.through>` model.
++
+ ``verbose_name``
+ ----------------
+
+Index: docs/ref/templates/builtins.txt
+===================================================================
+--- docs/ref/templates/builtins.txt (revision 16771)
++++ docs/ref/templates/builtins.txt (revision 17460)
+@@ -1868,7 +1868,7 @@
+ Returns a slice of the list.
+
+ Uses the same syntax as Python's list slicing. See
+-http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice
++http://diveintopython.net/native_data_types/lists.html#odbchelper.list.slice
+ for an introduction.
+
+ Example::
+Index: docs/ref/contrib/gis/geoip.txt
+===================================================================
+--- docs/ref/contrib/gis/geoip.txt (revision 16771)
++++ docs/ref/contrib/gis/geoip.txt (revision 17460)
+@@ -144,7 +144,7 @@
+ Returns a dictionary of city information for the given query. Some
+ of the values in the dictionary may be undefined (``None``).
+
+-.. method:: GeoIPcountry(query)
++.. method:: GeoIP.country(query)
+
+ Returns a dictionary with the country code and country for the given
+ query.
+Index: docs/ref/contrib/messages.txt
+===================================================================
+--- docs/ref/contrib/messages.txt (revision 16771)
++++ docs/ref/contrib/messages.txt (revision 17460)
+@@ -210,6 +210,10 @@
+ ``RequestContext``. Otherwise, ensure ``messages`` is available to
+ the template context.
+
++Even if you know there is only just one message, you should still iterate over
++the ``messages`` sequence, because otherwise the message storage will not be cleared
++for the next request.
++
+ Creating custom message levels
+ ------------------------------
+
+Index: docs/ref/contrib/admin/index.txt
+===================================================================
+--- docs/ref/contrib/admin/index.txt (revision 16771)
++++ docs/ref/contrib/admin/index.txt (revision 17460)
+@@ -19,8 +19,10 @@
+ 1. Add ``'django.contrib.admin'`` to your :setting:`INSTALLED_APPS`
+ setting.
+
+- 2. Admin has two dependencies - :mod:`django.contrib.auth` and
+- :mod:`django.contrib.contenttypes`. If these applications are not
++ 2. The admin has four dependencies - :mod:`django.contrib.auth`,
++ :mod:`django.contrib.contenttypes`,
++ :mod:`django.contrib.messages` and
++ :mod:`django.contrib.sessions`. If these applications are not
+ in your :setting:`INSTALLED_APPS` list, add them.
+
+ 3. Determine which of your application's models should be editable in the
+@@ -542,7 +544,7 @@
+ Fields in ``list_filter`` can also span relations using the ``__`` lookup::
+
+ class UserAdminWithLookup(UserAdmin):
+- list_filter = ('groups__name')
++ list_filter = ('groups__name',)
+
+ .. attribute:: ModelAdmin.list_per_page
+
+Index: docs/ref/django-admin.txt
+===================================================================
+--- docs/ref/django-admin.txt (revision 16771)
++++ docs/ref/django-admin.txt (revision 17460)
+@@ -1156,7 +1156,7 @@
+ Note that this option is unnecessary in ``manage.py``, because it takes care of
+ setting the Python path for you.
+
+-.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
++.. _import search path: http://diveintopython.net/getting_to_know_python/everything_is_an_object.html
+
+ .. django-admin-option:: --settings
+
+Index: docs/ref/signals.txt
+===================================================================
+--- docs/ref/signals.txt (revision 16771)
++++ docs/ref/signals.txt (revision 17460)
+@@ -352,12 +352,16 @@
+ .. data:: django.db.models.signals.post_syncdb
+ :module:
+
+-Sent by :djadmin:`syncdb` after it installs an application.
++Sent by :djadmin:`syncdb` command after it installs an application, and
++:djadmin:`flush` command.
+
+ Any handlers that listen to this signal need to be written in a particular
+ place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If
+ handlers are registered anywhere else they may not be loaded by
+-:djadmin:`syncdb`.
++:djadmin:`syncdb`. It is important that handlers of this signal perform
++idempotent changes (e.g. no database alterations) as this may cause the
++:djadmin:`flush` management command to fail if it also ran during the
++:djadmin:`syncdb` command.
+
+ Arguments sent with this signal:
+
+Index: README
+===================================================================
+--- README (revision 16771)
++++ README (revision 17460)
+@@ -28,7 +28,7 @@
+ To get more help:
+
+ * Join the #django channel on irc.freenode.net. Lots of helpful people
+- hang out there. Read the archives at http://botland.oebfare.com/logger/django/.
++ hang out there. Read the archives at http://django-irc-logs.com/.
+
+ * Join the django-users mailing list, or read the archives, at
+ http://groups.google.com/group/django-users.
diff --git a/libre/java-asm2/PKGBUILD b/libre/java-asm2/PKGBUILD
deleted file mode 100755
index 4853d79c0..000000000
--- a/libre/java-asm2/PKGBUILD
+++ /dev/null
@@ -1,76 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-
-_pkgname=asm
-pkgname=java-asm2
-_pkgver=2
-pkgver=2.2.3
-pkgrel=4
-pkgdesc="An all purpose Java bytecode manipulation and analysis framework."
-arch=('any')
-url="http://asm.ow2.org/"
-license=('custom:BSD3')
-depends=('java-runtime')
-makedepends=(
- apache-ant
- java-ow-util-ant-tasks
-)
-source=("http://download.forge.objectweb.org/$_pkgname/$_pkgname-$pkgver.tar.gz")
-
-_M2_LOCALREPO='/usr/share/maven/repository'
-_ow_util_ant_tasks='/usr/share/java/ow_util_ant_tasks.jar'
-_m2_packages=(
- asm
- asm-analysis
- asm-attrs
- asm-commons
- asm-tree
- asm-util
- asm-xml
- asm-all)
-
-build() {
- cd "$srcdir/$_pkgname-$pkgver"
-
- mkdir -p test/lib
-
- echo "objectweb.ant.tasks.path $_ow_util_ant_tasks" >> build.properties
- ant dist
-
- # This will make package() easier:
- cd output/dist/lib
- ln -s all/* .
-}
-
-package() {
- cd "$srcdir/$_pkgname-$pkgver"
-
- # Install license file
- install -Dm644 LICENSE.txt "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
-
- # Install documentation
- cd output/dist
- install -d "$pkgdir/usr/share/doc/$pkgname"
- cp -r doc/javadoc/user "$pkgdir/usr/share/doc/$pkgname/javadoc"
- cp -r examples "$pkgdir/usr/share/doc/$pkgname/examples"
-
- # Install Apache Maven modules
- cd lib
- install -d "$pkgdir"/usr/share/java/asm
- for pkg in "${_m2_packages[@]}"; do
- dir="$_M2_LOCALREPO"/asm/$pkg/$pkgver
- # Create the Maven directory
- install -d "$pkgdir$dir"
- # Install the files
- cp $pkg-$pkgver.* "$pkgdir$dir"
- # Symlink them to /usr/share/java
- ln -s "$dir"/$pkg-$pkgver.jar "$pkgdir"/usr/share/java/asm/
- ln -s asm/$pkg-$pkgver.jar "$pkgdir"/usr/share/java/$pkg-$_pkgver.jar
- done
-
- # Install a README file about the -all files
- cd "$srcdir/$_pkgname-$pkgver"
- install -m644 output/dist/lib/all/README.txt \
- "$pkgdir"/usr/share/java/asm/README-$pkgver.txt
-}
-
-md5sums=('7a92c87bf067925685cf68dcc0dd8998')
diff --git a/libre/java-asm3/PKGBUILD b/libre/java-asm3/PKGBUILD
deleted file mode 100755
index 7e66a5b5a..000000000
--- a/libre/java-asm3/PKGBUILD
+++ /dev/null
@@ -1,78 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-
-_pkgname=asm
-pkgname=java-asm3
-_pkgver=3
-pkgver=3.3.1
-pkgrel=4.1
-pkgdesc="An all purpose Java bytecode manipulation and analysis framework."
-arch=('any')
-url="http://asm.ow2.org/"
-license=('custom:BSD3')
-depends=('java-runtime')
-makedepends=(
- apache-ant
- java-ow-util-ant-tasks
-)
-source=("http://download.forge.objectweb.org/$_pkgname/$_pkgname-$pkgver.tar.gz")
-
-_M2_LOCALREPO='/usr/share/maven/repository'
-_ow_util_ant_tasks='/usr/share/java/ow_util_ant_tasks.jar'
-_m2_packages=(
- asm
- asm-analysis
- asm-commons
- asm-parent
- asm-tree
- asm-util
- asm-xml
- asm-all
- asm-debug-all)
-
-build() {
- cd "$srcdir/$_pkgname-$pkgver"
-
- rm cobertura.ser # We regenerate this
- rm examples/jasmin/test/jasmin.jar
-
- echo "objectweb.ant.tasks.path $_ow_util_ant_tasks" >> build.properties
- ant dist
-
- # This will make package() easier:
- cd output/dist/lib
- ln -s all/* .
-}
-
-package() {
- cd "$srcdir/$_pkgname-$pkgver"
-
- # Install license file
- install -Dm644 LICENSE.txt "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
-
- # Install documentation
- cd output/dist
- install -d "$pkgdir/usr/share/doc/$pkgname"
- cp -r doc/javadoc/user "$pkgdir/usr/share/doc/$pkgname/javadoc"
- cp -r examples "$pkgdir/usr/share/doc/$pkgname/examples"
-
- # Install Apache Maven modules
- cd lib
- install -d "$pkgdir"/usr/share/java/asm
- for pkg in "${_m2_packages[@]}"; do
- dir="$_M2_LOCALREPO"/asm/$pkg/$pkgver
- # Create the Maven directory
- install -d "$pkgdir$dir"
- # Install the files
- cp $pkg-$pkgver.* "$pkgdir$dir"
- # Symlink them to /usr/share/java
- ln -s "$dir"/$pkg-$pkgver.jar "$pkgdir"/usr/share/java/asm/
- ln -s asm/$pkg-$pkgver.jar "$pkgdir"/usr/share/java/$pkg-$_pkgver.jar
- done
-
- # Install a README file about the -all files
- cd "$srcdir/$_pkgname-$pkgver"
- install -m644 output/dist/lib/all/README.txt \
- "$pkgdir"/usr/share/java/asm/README-$pkgver.txt
-}
-
-md5sums=('433024df8176f09922646316e415631c')
diff --git a/libre/java-ow-util-ant-tasks/PKGBUILD b/libre/java-ow-util-ant-tasks/PKGBUILD
deleted file mode 100755
index 023048188..000000000
--- a/libre/java-ow-util-ant-tasks/PKGBUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-
-pkgname=java-ow-util-ant-tasks
-pkgver=1.3.2
-pkgrel=1
-pkgdesc="ObjectWeb utility Ant tasks library"
-arch=('any')
-url="http://forge.ow2.org/projects/monolog"
-license=('LGPL')
-depends=('java-environment')
-makedepends=('apache-ant' 'xalan-java' 'java-asm2')
-source=("http://repo.parabolagnulinux.org/sources/${pkgname}-${pkgver}-1-any.src.tar.xz")
-
-build() {
- cd "$srcdir/$pkgname-$pkgver"
- ln -s /usr/share/java/asm-2.jar externals
- ln -s /usr/share/java/xalan.jar externals
- ant jar
-}
-
-package() {
- cd "$srcdir/$pkgname-$pkgver"
- install -d "$pkgdir"/usr/share/java
- install -m644 "output/lib/ow_util_ant_tasks.jar" "$pkgdir"/usr/share/java
-}
-
-md5sums=('339b3eb4b2960473a42f5f781afbeca6')
diff --git a/libre/java-ow-util-ant-tasks/SRCBUILD b/libre/java-ow-util-ant-tasks/SRCBUILD
deleted file mode 100755
index 01241907d..000000000
--- a/libre/java-ow-util-ant-tasks/SRCBUILD
+++ /dev/null
@@ -1,29 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-
-pkgname=java-ow-util-ant-tasks
-pkgver=1.3.2
-pkgrel=1
-pkgdesc="ObjectWeb utility Ant tasks library"
-arch=('any')
-url="http://forge.ow2.org/projects/monolog"
-license=('LGPL')
-source=("http://download.forge.objectweb.org/monolog/ow_util_ant_tasks_$pkgver.zip")
-noextract=("ow_util_ant_tasks_$pkgver.zip")
-
-build() {
- cd "$srcdir"
- mkdir $pkgname-$pkgver
- cd $pkgname-$pkgver
- bsdtar xf "$srcdir"/ow_util_ant_tasks_$pkgver.zip
- rm -rf output
- rm externals/*
-}
-
-
-package() {
- PKGEXT=${SRCEXT}
- PKGDEST=${SRCDEST}
- cp -a "$srcdir/$pkgname-$pkgver" "$pkgdir/"
-}
-
-md5sums=('cd602bf75a0feab480fa97739955b84e')
diff --git a/libre/maven-libre/PKGBUILD b/libre/maven-libre/PKGBUILD
deleted file mode 100755
index 2bd99940e..000000000
--- a/libre/maven-libre/PKGBUILD
+++ /dev/null
@@ -1,76 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-# Maintainer (Arch): Sergej Pupykin <pupykin.s+arch@gmail.com>
-# Contributor: William Rea <sillywilly@gmail.com>
-
-_pkgname=maven
-pkgname=maven-libre
-pkgver=3.0.4
-
-provides=("$_pkgname=$pkgver")
-replaces=("$_pkgname")
-conflicts=("$_pkgname")
-
-pkgrel=1
-pkgdesc="A Java project management and project comprehension tool"
-arch=('any')
-url="http://maven.apache.org"
-license=('Apache')
-depends=('java-environment')
-makedepends=('apache-ant')
-backup=('etc/maven/settings.xml')
-
-_mirror=http://archive.apache.org/dist
-source=($_mirror/maven/source/apache-maven-$pkgver-src.tar.gz
- maven.sh maven.csh)
-
-_M2_LOCALREPO="/usr/share/maven/repository"
-
-# FIXME: This also does tasks for package()
-build() {
- cd $srcdir/apache-maven-$pkgver
-
- . /etc/profile.d/jre.sh
- . /etc/profile.d/jdk.sh
-
- export MAVEN_OPTS=-Xmx512m
- export M2_HOME="$pkgdir"/opt/maven
- export PATH="$PATH:$M2_HOME/bin"
-
- # FIXME: Downloads many deps from Internet. They should be
- # packaged separately and added to depends=()
- install -d "$pkgdir`dirname $_M2_LOCALREPO`"
- cp -r $_M2_LOCALREPO "$pkgdir$_M2_LOCALREPO"
- install -d "$pkgdir"/opt
- ant -Dmaven.repo.local="$pkgdir$_M2_LOCALREPO"
- rm "$pkgdir"/opt/maven/*.txt
-}
-
-package() {
- install -d "$pkgdir$_M2_LOCALREPO"
-
- # Install config file in /etc
- # Unlike the other directories, we symlink from the system to /opt/maven
- # because that way all conf files stay in /etc
- install -d "$pkgdir"/etc/maven
- sed "55i<localRepository>$_M2_LOCALREPO</localRepository>" \
- < "$pkgdir"/opt/maven/conf/settings.xml \
- > "$pkgdir"/etc/maven/settings.xml
- rm -rf "$pkgdir"/opt/maven/conf
- ln -s /etc/maven "$pkgdir"/opt/maven/conf
-
- # Install profile.d settings
- install -d "$pkgdir"/etc/profile.d
- install -m 755 "$srcdir"/maven.{csh,sh} "$pkgdir"/etc/profile.d
-
- # Link executables to /usr/bin
- install -d "$pkgdir"/usr/bin
- ln -s /opt/maven/bin/{mvn,mvnDebug,mvnyjp} "$pkgdir"/usr/bin
-
- # Link jar files to appropriate place in /usr/share
- install -d "$pkgdir"/usr/share/java
- ln -s /opt/maven/lib "$pkgdir"/usr/share/java/maven
-}
-
-md5sums=('17ca94d5be05a78c6ab12425b7a0ee10'
- '58820067a4d7384477daa134023d9b57'
- 'e2bbdeffed100cd51d05b2ba8ebd6321')
diff --git a/libre/maven-libre/maven.csh b/libre/maven-libre/maven.csh
deleted file mode 100755
index f5750cfc8..000000000
--- a/libre/maven-libre/maven.csh
+++ /dev/null
@@ -1,2 +0,0 @@
-setenv MAVEN_OPTS -Xmx512m
-setenv M2_HOME=/opt/maven
diff --git a/libre/maven-libre/maven.sh b/libre/maven-libre/maven.sh
deleted file mode 100755
index b6655cc22..000000000
--- a/libre/maven-libre/maven.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-export MAVEN_OPTS=-Xmx512m
-export M2_HOME=/opt/maven
diff --git a/libre/parabolaweb-git/Makefile b/libre/parabolaweb-git/Makefile
deleted file mode 100755
index 55115aba3..000000000
--- a/libre/parabolaweb-git/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-all:
- makepkg
-
-python_packages=south
-python2_packages=markdown|psycopg2|pyinotify|pytz
-requirements= https://projects.parabolagnulinux.org/parabolaweb.git/plain/requirements_prod.txt
-
-requirements_prod.txt: WEB
- rm -f $@
- wget --no-check-certificate $(requirements)
-
-deps-ver.txt: requirements_prod.txt
- sed -r -e 's/.*/\L&/' -e 's/==/=/' \
- -e 's/^(${python_packages})/python-&/' \
- -e 's/^(${python2_packages})/python2-&/' $< >$@
-
-deps-nover.txt: deps-ver.txt
- sed 's/[<>=].*//' $< >$@
-
-clean:
- rm requirements_prod.txt deps-ver.txt deps-nover.txt
-
-WEB: FORCE
-FORCE: PHONY
-PHONY:
-.PHONY: PHONY
diff --git a/libre/parabolaweb-git/PKGBUILD b/libre/parabolaweb-git/PKGBUILD
deleted file mode 100755
index 4641ea8d3..000000000
--- a/libre/parabolaweb-git/PKGBUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
-
-pkgname=parabolaweb-git
-pkgver=20120506
-pkgrel=3
-pkgdesc="The Parabola website, fork of archweb"
-arch=('any')
-url="https://projects.parabolagnulinux.org/parabolaweb.git/"
-license=('GPL2')
-
-_deps_file=deps-ver.txt
-#_deps_file=deps-nover.txt
-make "$_deps_file" 1>&2
-depends=('python2' 'git' 'libretools' `cat $_deps_file`)
-
-source=('parabolaweb.init.sh' 'parabolaweb.update.sh.in')
-
-# These will make it install into /http/srv/web
-_install_dir=/srv/http
-_gitname=web
-
-_gitroot=https://projects.parabolagnulinux.org/parabolaweb.git
-_gitbranch="master"
-
-build() {
- cd "${srcdir}"
- sed \
- -e "s|^_install_dir=.*|_install_dir='$_install_dir'|" \
- -e "s|^_gitname=.*|_gitname='$_gitname'|" \
- -e "s|^_gitroot=.*|_gitroot='$_gitroot'|" \
- -e "s|^_gitbranch=.*|_gitbranch='$_gitbranch'|" \
- < parabolaweb.update.sh.in > parabolaweb.update.sh
-}
-
-package() {
- cd "${srcdir}"
- install -d "${pkgdir}/${_install_dir}"
- install -Dm755 parabolaweb.init.sh "${pkgdir}/etc/rc.d/parabolaweb"
- install -Dm755 parabolaweb.update.sh "${pkgdir}/usr/sbin/parabolaweb.update"
-}
-
-md5sums=('72bc7092e4e50a2aaca8b871644520d9'
- 'f495b2e4623691925308cb4a1ec7e5a9')
diff --git a/libre/parabolaweb-git/deps-ver.txt b/libre/parabolaweb-git/deps-ver.txt
deleted file mode 100755
index 67fe6848b..000000000
--- a/libre/parabolaweb-git/deps-ver.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-django=1.3.1
-python2-markdown>=2.0.3
-python2-psycopg2
-python-south>=0.7.3
-python2-pyinotify>=0.9.2
-python-memcached>=1.47
-python2-pytz>=2011n
diff --git a/libre/parabolaweb-git/parabolaweb.init.sh b/libre/parabolaweb-git/parabolaweb.init.sh
deleted file mode 100755
index cb9f2441e..000000000
--- a/libre/parabolaweb-git/parabolaweb.init.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-
-. /etc/rc.conf
-. /etc/rc.d/functions
-
-HOST=127.0.0.1
-PORT=8090 # 80 is nginx
-PIDFILE=/var/run/web/fcgi.pid
-
-case $1 in
-start)
- stat_busy "Starting ParabolaWeb"
- if [[ -e /srv/http/web/manage.py ]]; then
- sudo -u nobody \
- python2 /srv/http/web/manage.py runfcgi \
- host=${HOST} \
- port=${PORT} \
- pidfile=${PIDFILE} \
- --settings=settings
-
- add_daemon parabolaweb
- stat_done
- exit 0
- else
- stat_fail
- exit 1
- fi
- ;;
-
-stop)
- stat_busy "Stopping ParabolaWeb"
- if [[ -f ${PIDFILE} ]]; then
- pid=$(cat ${PIDFILE})
- kill ${pid}
- rm_daemon parabolaweb
- stat_done
- else
- stat_fail
- exit 1
- fi
- ;;
-
-restart)
- $0 stop
- $0 start
- ;;
-
-*)
- echo "Usage: $0 {start|stop|restart}" >&2
- exit 1
-
-esac
diff --git a/libre/parabolaweb-git/parabolaweb.update.sh.in b/libre/parabolaweb-git/parabolaweb.update.sh.in
deleted file mode 100755
index 8c3aef0f0..000000000
--- a/libre/parabolaweb-git/parabolaweb.update.sh.in
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-set -e
-
-_install_dir=@INSTALL_DIR@
-_gitname=@GIT_NAME@
-
-_gitroot=@GITROOT@
-_gitbranch=@GITBRANCH@
-
-. /usr/bin/libremessages
-
-if [ ! -d "$_install_dir" ]; then
- mkdir "$_install_dir"
-fi
-cd "$_install_dir"
-
-msg "Connecting to GIT server...."
-if [ -d ${_gitname} ] ; then
- msg2 "Updating existing tree"
- cd ${_gitname} && git pull ${_gitroot}
-else
- msg2 "Cloning tree"
- git clone ${_gitroot} ${_gitname}
- cd ${_gitname}
-fi
-git checkout ${_gitbranch}
-msg "GIT checkout done or server timeout"
-
-msg "Purging old .pyc files...."
-find . -name '*.pyc' -delete
-
-msg "Checking configuration...."
-if [ ! -f local_settings.py ]; then
- cp local_settings.py.example local_settings.tmp.$$.py
- if ${EDITOR:-xdg-open} local_settings.tmp.$$.py; then
- mv local_settings.tmp.$$.py local_settings.py
- else
- rm local_settings.tmp.$$.py
- msg "Failed to configure, exiting"
- exit 1
- fi
- msg "Creating database...."
- ./manage.py syncdb
-fi
-
-msg "Purging old .pyc files...."
-find . -name '*.pyc' -delete
-
-msg "Updating database...."
-msg2 "Running migrations...."
-./manage.py migrate
-msg2 "Loading fixtures...."
-./manage.py loaddata */fixtures/*.json
-
-msg "Checking media/admin_media symlink...."
-if [ ! -e media/admin-media ]; then
- rm media/admin_media
- ln -s /usr/lib/python2.7/site-packages/django/contrib/admin/media media/admin_media
-fi
diff --git a/libre/parabolaweb-git/requirements_prod.txt b/libre/parabolaweb-git/requirements_prod.txt
deleted file mode 100755
index 78eb51250..000000000
--- a/libre/parabolaweb-git/requirements_prod.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Django==1.3.1
-Markdown>=2.0.3
-psycopg2
-South>=0.7.3
-pyinotify>=0.9.2
-python-memcached>=1.47
-pytz>=2011n
diff --git a/libre/parabolaweb-utils/PKGBUILD b/libre/parabolaweb-utils/PKGBUILD
new file mode 100644
index 000000000..cfb39d703
--- /dev/null
+++ b/libre/parabolaweb-utils/PKGBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Luke Shumaker <lukeshu@sbcglobal.net>
+
+. helper.sh
+# provides:
+# _get_pkgver
+# _get_depends
+# _get_depends_nover (no version requirements)
+
+pkgname=parabolaweb-utils
+pkgver=`_get_pkgver`
+pkgrel=2
+pkgdesc="Utils for the Parabola website"
+arch=('any')
+url="https://projects.parabolagnulinux.org/parabolaweb.git/"
+license=('GPL2')
+depends=('python2' 'python2-flup' 'git' 'libretools' `_get_depends`)
+backup=('etc/conf.d/parabolaweb')
+
+export pkgver
+
+source=(git://parabolagnulinux.org/parabolaweb.git
+ parabolaweb-update
+ parabolaweb-fcgi
+ parabolaweb.rc
+ parabolaweb.service
+ parabolaweb.conf)
+
+build() {
+ :
+}
+
+package() {
+ cd "${srcdir}"
+ install -Dm755 parabolaweb-update "${pkgdir}/usr/sbin/parabolaweb-update"
+ install -Dm755 parabolaweb-fcgi "${pkgdir}/usr/sbin/parabolaweb-fcgi"
+ install -Dm755 parabolaweb.rc "${pkgdir}/etc/rc.d/parabolaweb"
+ install -Dm644 parabolaweb.service "${pkgdir}/usr/lib/systemd/system/parabolaweb.service"
+ install -Dm644 parabolaweb.conf "${pkgdir}/etc/conf.d/parabolaweb"
+}
+
+md5sums=('SKIP'
+ 'dd05d6a4ea7cff7fdd789f59aeb9059a'
+ '520e20b8bbca64042b3afa76b0bec55f'
+ '1bce8fb832ad9e61cf8b96426ce843b5'
+ 'c7e292d2d1c3e846e5cfcd7283de0fe4'
+ 'fb291168d3f57a85f82216c4e74c9ccf')
diff --git a/libre/parabolaweb-utils/helper.sh b/libre/parabolaweb-utils/helper.sh
new file mode 100644
index 000000000..5ce4182b3
--- /dev/null
+++ b/libre/parabolaweb-utils/helper.sh
@@ -0,0 +1,39 @@
+_mksource() {
+ if [[ -z _DO_NOT_RUN_MKSOURCE ]]; then
+ _DO_NOT_RUN_MKSOURCE=true makepkg -o
+ fi
+}
+
+_get_pkgver() {
+ if [[ -n $pkgver ]] && [[ $pkgver != 0.bogus ]]; then
+ echo $pkgver
+ else
+ _mksource 1>&2
+ if [[ -f "${srcdir:-src}/parabolaweb/requirements_prod.txt" ]]; then
+ pushd "${srcdir:-src}/parabolaweb" >/dev/null
+ # get the date requirements_prod.txt was last modified
+ gitdate="$(git log -n1 --date=iso --format=format:'%cd' ./requirements_prod.txt)"
+ date -u +%Y%m%d.%H%M -d "$gitdate"
+ popd >/dev/null
+ else
+ echo 0.bogus
+ fi
+ fi
+}
+
+_get_depends() {
+ _mksource 1>&2
+ if [[ -f "${srcdir:-src}/parabolaweb/requirements_prod.txt" ]]; then
+ pushd "${srcdir:-src}" >/dev/null
+ python2_packages='markdown|psycopg2|pyinotify|pytz|south'
+ < parabolaweb/requirements_prod.txt sed -r \
+ -e 's/.*/\L&/' -e 's/==/=/' \
+ -e 's/^python-memcached/python2-memcached/' \
+ -e "s/^(${python2_packages})/python2-&/"
+ popd >/dev/null
+ fi
+}
+
+_get_depends_nover() {
+ _get_depends | sed 's/[<>=].*//'
+}
diff --git a/libre/parabolaweb-utils/parabolaweb-fcgi b/libre/parabolaweb-utils/parabolaweb-fcgi
new file mode 100644
index 000000000..3dec02e10
--- /dev/null
+++ b/libre/parabolaweb-utils/parabolaweb-fcgi
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -e
+
+. /etc/conf.d/parabolaweb
+
+[[ -e /srv/http/web/manage.py ]]
+
+sudo -u "${WEBUSER:-$USER}" python2 /srv/http/web/manage.py runfcgi \
+ host=${HOST} \
+ port=${PORT} \
+ --settings=settings \
+ "$@"
diff --git a/libre/parabolaweb-utils/parabolaweb-update b/libre/parabolaweb-utils/parabolaweb-update
new file mode 100644
index 000000000..e4d65c2d9
--- /dev/null
+++ b/libre/parabolaweb-utils/parabolaweb-update
@@ -0,0 +1,81 @@
+#!/bin/bash
+set -e
+
+_install_dir=/srv/http
+_gitname=web
+_gitroot=git://parabolagnulinux.org/parabolaweb.git
+_gitbranch=master
+
+. /usr/bin/libremessages
+
+download() {
+ msg "Connecting to GIT server...."
+ cd "$_install_dir"
+ if [[ -d ${_gitname} ]]; then
+ msg2 "Updating existing tree"
+ cd ${_gitname} && git pull ${_gitroot}
+ else
+ msg2 "Cloning tree"
+ git clone ${_gitroot} ${_gitname}
+ cd ${_gitname}
+ fi
+ git checkout ${_gitbranch}
+ msg "GIT checkout done or server timeout"
+}
+
+clean() {
+ msg "Purging old .pyc files...."
+ cd "$_install_dir/$_gitname"
+ find . -name '*.pyc' -delete
+}
+
+configure() {
+ msg "Checking configuration...."
+ cd "$_install_dir/$_gitname"
+ if [[ ! -f local_settings.py ]]; then
+ msg2 "Configuration file missing, opening editor..."
+ cp local_settings.py.example local_settings.tmp.$$.py
+ if "$EDITOR" local_settings.tmp.$$.py; then
+ mv local_settings.tmp.$$.py local_settings.py
+ else
+ rm local_settings.tmp.$$.py
+ msg "Failed to configure, exiting"
+ exit 1
+ fi
+ msg2 "Creating database...."
+ ./manage.py syncdb
+ else
+ msg2 "Current configuration checks out"
+ fi
+}
+
+migrate() {
+ msg "Updating database...."
+ msg2 "Running migrations...."
+ ./manage.py migrate
+ msg2 "Loading fixtures...."
+ ./manage.py loaddata */fixtures/*.json
+}
+
+main() {
+ if [[ -z "$EDITOR" ]]; then
+ error 'Please set the $EDITOR variable'
+ exit 1
+ fi
+
+ [[ ! -d "$_install_dir" ]] && mkdir "$_install_dir"
+
+ download
+ clean
+ configure
+ clean
+ migrate
+
+ msg "Checking media/admin_media symlink...."
+ if [ ! -e media/admin-media ]; then
+ rm media/admin_media
+ ln -s /usr/lib/python2.7/site-packages/django/contrib/admin/media media/admin_media
+ fi
+}
+
+main "$@"
diff --git a/libre/parabolaweb-utils/parabolaweb.conf b/libre/parabolaweb-utils/parabolaweb.conf
new file mode 100644
index 000000000..c53b19cb8
--- /dev/null
+++ b/libre/parabolaweb-utils/parabolaweb.conf
@@ -0,0 +1,3 @@
+HOST=127.0.0.1
+PORT=8090 # 80 is nginx
+WEBUSER=nobody
diff --git a/libre/parabolaweb-utils/parabolaweb.rc b/libre/parabolaweb-utils/parabolaweb.rc
new file mode 100644
index 000000000..087a3fcb0
--- /dev/null
+++ b/libre/parabolaweb-utils/parabolaweb.rc
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+. /etc/rc.conf
+. /etc/rc.d/functions
+
+PIDFILE=/run/web/parabolaweb.pid
+
+case $1 in
+start)
+ stat_busy "Starting ParabolaWeb"
+ if parabolaweb-fcgi pidfile=${PIDFILE}; then
+ add_daemon parabolaweb
+ stat_done
+ exit 0
+ else
+ stat_fail
+ exit 1
+ fi
+ ;;
+
+stop)
+ stat_busy "Stopping ParabolaWeb"
+ if [[ -f ${PIDFILE} ]]; then
+ pid=$(cat ${PIDFILE})
+ kill ${pid}
+ rm_daemon parabolaweb
+ stat_done
+ else
+ stat_fail
+ exit 1
+ fi
+ ;;
+
+restart)
+ $0 stop
+ $0 start
+ ;;
+
+*)
+ echo "Usage: $0 {start|stop|restart}" >&2
+ exit 1
+
+esac
diff --git a/libre/parabolaweb-utils/parabolaweb.service b/libre/parabolaweb-utils/parabolaweb.service
new file mode 100644
index 000000000..d145e53d8
--- /dev/null
+++ b/libre/parabolaweb-utils/parabolaweb.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=ParabolaWeb
+
+[Service]
+Type=forking
+ExecStart=/usr/sbin/parabolaweb-fcgi pidfile=/run/web/parabolaweb.pid
+PIDFile=/run/web/parabolaweb.pid
+
+[Install]
+WantedBy=multi-user.target
diff --git a/libre/tp_smapi-libre-lts/PKGBUILD b/libre/tp_smapi-libre-lts/PKGBUILD
new file mode 100644
index 000000000..91ae34864
--- /dev/null
+++ b/libre/tp_smapi-libre-lts/PKGBUILD
@@ -0,0 +1,60 @@
+# Maintainer: Lukas Fleischer <archlinux at cryptocrack dot de>
+# Contributor: xduugu
+# Contributor: nh2
+# Contributor: Steven Davidovitz <steviedizzle ð gmail đ com>
+# Contributor: Nick B <Shirakawasuna ð gmail đ com>
+# Contributor: Christof Musik <christof ð senfdax đ de>
+# Contributor: Stefan Rupp <archlinux ð stefanrupp đ de>
+# Contributor: Ignas Anikevicius <anikevicius ð gmail đ com>
+# Maintainer (Parabola): André Silva <emulatorman@lavabit.com>
+
+pkgname=tp_smapi-libre-lts
+_pkgname=tp_smapi
+_extramodules=/usr/lib/modules/extramodules-3.0-LIBRE-LTS
+pkgver=0.41
+pkgrel=9
+pkgdesc="linux-libre-lts modules for ThinkPad's SMAPI functionality"
+arch=('i686' 'x86_64')
+url='https://github.com/evgeni/tp_smapi'
+license=('GPL')
+depends=('linux-libre-lts>=3.0' 'linux-libre-lts<3.1')
+makedepends=('linux-libre-lts-headers>=3.0' 'linux-libre-lts-headers<3.1')
+replaces=('tp_smapi-lts')
+conflicts=('tp_smapi-lts')
+provides=("tp_smapi-lts=${pkgver}")
+install='tp_smapi-lts.install'
+source=("https://github.com/downloads/evgeni/${_pkgname}/${_pkgname}-${pkgver}.tar.gz")
+md5sums=('63c683415c764568f6bf17c7eabe4752')
+
+build() {
+ cd "${srcdir}/${_pkgname}-${pkgver}"
+
+ _kernver=$(< "${_extramodules}/version")
+
+ sed -ri -e "s/^(KVER\s*:=).*$/\1 ${_kernver}/" \
+ -e "s#^(KBASE\s*:=).*\$#\1 ${_extramodules%/*}/${_kernver}#" Makefile
+
+ make HDAPS=1
+}
+
+package() {
+ _kernver=$(< "${_extramodules}/version")
+
+ make -C "${_extramodules%/*}/${_kernver}/build" \
+ INSTALL_MOD_PATH="${pkgdir}/${_extramodules%%/lib/*}" \
+ M="${srcdir}/${_pkgname}-${pkgver}" modules_install
+
+ cd "${pkgdir}/${_extramodules%/*}"
+ mv "${_kernver}/extra" "${_extramodules##*/}"
+ rmdir "${_kernver}"
+
+ # compress kernel modules
+ find "${pkgdir}" -name "*.ko" -exec gzip -9 {} +
+
+ # load module on startup
+ echo tp_smapi > "${srcdir}/tp_smapi-lts.conf"
+ install -Dm644 "${srcdir}/tp_smapi-lts.conf" "${pkgdir}/usr/lib/modules-load.d/tp_smapi-lts.conf"
+
+ # update kernel version in install file
+ sed -ri "s#^(extramodules=).*\$#\1${_extramodules}#" "${startdir}/tp_smapi-lts.install"
+}
diff --git a/libre/tp_smapi-libre-lts/tp_smapi-lts.install b/libre/tp_smapi-libre-lts/tp_smapi-lts.install
new file mode 100644
index 000000000..2723fead7
--- /dev/null
+++ b/libre/tp_smapi-libre-lts/tp_smapi-lts.install
@@ -0,0 +1,13 @@
+extramodules=/usr/lib/modules/extramodules-3.0-LIBRE-LTS
+
+post_install() {
+ depmod -v $(< "$extramodules/version") &>/dev/null
+}
+
+post_upgrade() {
+ post_install
+}
+
+post_remove() {
+ post_install
+}
diff --git a/libre/virtualbox-libre-modules-lts/PKGBUILD b/libre/virtualbox-libre-modules-lts/PKGBUILD
index dff627829..7a95b4c7b 100644
--- a/libre/virtualbox-libre-modules-lts/PKGBUILD
+++ b/libre/virtualbox-libre-modules-lts/PKGBUILD
@@ -7,8 +7,8 @@
pkgbase=virtualbox-libre-modules-lts
pkgname=('virtualbox-libre-host-modules-lts' 'virtualbox-libre-guest-modules-lts')
-pkgver=4.2.0
-pkgrel=3.1
+pkgver=4.2.2
+pkgrel=1
arch=('i686' 'x86_64')
url='http://virtualbox.org'
license=('GPL')
@@ -40,8 +40,7 @@ package_virtualbox-libre-host-modules-lts(){
install=virtualbox-libre-host-modules-lts.install
_kernver=$(expac -Q '%v' linux-libre-lts-headers)-LIBRE-LTS
- #_extraver=extramodules-${_kernver%.*}-LIBRE-LTS
- _extraver=extramodules-3.0-LIBRE-LTS
+ _extraver=extramodules-${_kernver%.*}-LIBRE-LTS
install -dm755 "$pkgdir/usr/lib/modules/$_extraver"
cd "dkms/vboxhost/$pkgver/$_kernver/$CARCH/module"
@@ -60,8 +59,7 @@ package_virtualbox-libre-guest-modules-lts(){
install=virtualbox-libre-guest-modules-lts.install
_kernver=$(expac -Q '%v' linux-libre-lts-headers)-LIBRE-LTS
- #_extraver=extramodules-${_kernver%.*}-LIBRE-LTS
- _extraver=extramodules-3.0-LIBRE-LTS
+ _extraver=extramodules-${_kernver%.*}-LIBRE-LTS
install -dm755 "$pkgdir/usr/lib/modules/$_extraver"
cd "dkms/vboxguest/$pkgver/$_kernver/$CARCH/module"
diff --git a/libre/virtualbox-libre-modules/PKGBUILD b/libre/virtualbox-libre-modules/PKGBUILD
index 10182a0e9..3fcbd7069 100755
--- a/libre/virtualbox-libre-modules/PKGBUILD
+++ b/libre/virtualbox-libre-modules/PKGBUILD
@@ -6,8 +6,8 @@
pkgbase=virtualbox-libre-modules
pkgname=('virtualbox-libre-host-modules' 'virtualbox-libre-guest-modules')
-pkgver=4.2.0
-pkgrel=6.1
+pkgver=4.2.2
+pkgrel=1
arch=('i686' 'x86_64')
url='http://virtualbox.org'
license=('GPL')
diff --git a/libre/virtualbox-libre/vboxdrv-reference.patch b/libre/virtualbox-libre/001-vboxdrv-reference.patch
index 51fd6361c..51fd6361c 100644
--- a/libre/virtualbox-libre/vboxdrv-reference.patch
+++ b/libre/virtualbox-libre/001-vboxdrv-reference.patch
diff --git a/libre/virtualbox-libre/change_default_driver_dir.patch b/libre/virtualbox-libre/002-change_default_driver_dir.patch
index d8531499d..d8531499d 100755
--- a/libre/virtualbox-libre/change_default_driver_dir.patch
+++ b/libre/virtualbox-libre/002-change_default_driver_dir.patch
diff --git a/libre/virtualbox-libre/003-remove_qt_fa_IR.patch b/libre/virtualbox-libre/003-remove_qt_fa_IR.patch
new file mode 100644
index 000000000..58e6235d5
--- /dev/null
+++ b/libre/virtualbox-libre/003-remove_qt_fa_IR.patch
@@ -0,0 +1,23 @@
+# seblu 10/2012 - fucking farci removing patch
+
+--- a/src/VBox/Frontends/VirtualBox/nls/ApprovedLanguages.kmk 2012-10-18 16:22:52.000000000 +0200
++++ b/src/VBox/Frontends/VirtualBox/nls/ApprovedLanguages.kmk 2012-10-19 03:03:52.640867388 +0200
+@@ -23,7 +23,6 @@
+ de \
+ en \
+ es \
+- fa_IR \
+ hu \
+ it \
+ ja \
+
+--- a/src/VBox/Frontends/VirtualBox/VBoxUI.pro 2012-10-18 16:22:47.000000000 +0200
++++ b/src/VBox/Frontends/VirtualBox/VBoxUI.pro 2012-10-20 02:48:37.525765901 +0200
+@@ -63,7 +63,6 @@
+ nls/VirtualBox_es.ts \
+ nls/VirtualBox_eu.ts \
+ nls/VirtualBox_fi.ts \
+- nls/VirtualBox_fa_IR.ts \
+ nls/VirtualBox_fr.ts \
+ nls/VirtualBox_gl_ES.ts \
+ nls/VirtualBox_hu.ts \
diff --git a/libre/virtualbox-libre/PKGBUILD b/libre/virtualbox-libre/PKGBUILD
index 5ae72a76f..9e1d74cac 100755
--- a/libre/virtualbox-libre/PKGBUILD
+++ b/libre/virtualbox-libre/PKGBUILD
@@ -12,8 +12,8 @@ pkgname=('virtualbox-libre'
'virtualbox-libre-host-source'
'virtualbox-libre-guest-utils'
'virtualbox-libre-guest-source')
-pkgver=4.2.0
-pkgrel=4.1
+pkgver=4.2.2
+pkgrel=1
arch=('i686' 'x86_64')
url='http://virtualbox.org'
license=('GPL' 'custom')
@@ -56,8 +56,9 @@ source=("http://download.virtualbox.org/virtualbox/$pkgver/VirtualBox-$pkgver.ta
'vboxweb.conf'
'vboxweb.rc'
'vboxweb.service'
- 'change_default_driver_dir.patch'
- 'vboxdrv-reference.patch'
+ '001-vboxdrv-reference.patch'
+ '002-change_default_driver_dir.patch'
+ '003-remove_qt_fa_IR.patch'
'os_blag_64.png'
'os_blag.png'
'os_dragora_64.png'
@@ -78,7 +79,7 @@ source=("http://download.virtualbox.org/virtualbox/$pkgver/VirtualBox-$pkgver.ta
'os_venenux.png'
'libre.patch'
'free-distros.patch')
-md5sums=('691b4134983ce7d89b9fb683305cb647'
+md5sums=('2b65dcd9649e56ac6338670b3fb4a14d'
'5f85710e0b8606de967716ded7b2d351'
'ed1341881437455d9735875ddf455fbe'
'58d6e5bb4b4c1c6f3f0b3daa6aaeed03'
@@ -88,8 +89,9 @@ md5sums=('691b4134983ce7d89b9fb683305cb647'
'7e9483b1069a54f181546083ac7e5469'
'c159d683ba1947290fc2ad2c64194150'
'bc9efed88e0469cd7fc460d5a5cd7b4b'
- '97e193f050574dd272a38e5ee5ebe62b'
'4f1692638d6740df4c4ad9766ba4e179'
+ '97e193f050574dd272a38e5ee5ebe62b'
+ '866ce76a94fb22cc7b625e07e571f0ad'
'8538dba8686d7449cb481c9bae9d722a'
'545c925b46f2ac95e5f8ae407fad101a'
'f6416f509c2e5460e4dc624e0a57f3c1'
@@ -108,7 +110,7 @@ md5sums=('691b4134983ce7d89b9fb683305cb647'
'c7951fe6888d939f3a7d0dafe477e82b'
'4da8eeb2ece7e475fc7a0d1003da26c6'
'5e4187af59726d71c5be48d0cd816c34'
- '67cc4c8611890038eb3e4114ae899525'
+ '85141ccd2621a8e004b8f55c9a1f83eb'
'c7b29fbf4c24a00e8646ca6dd73f38a1')
#_extramodules=extramodules-3.5-LIBRE
@@ -117,15 +119,21 @@ md5sums=('691b4134983ce7d89b9fb683305cb647'
build() {
cd "VirtualBox-$pkgver"
- patch -Np1 -i "$srcdir/vboxdrv-reference.patch"
- patch -Np1 -i "$srcdir/change_default_driver_dir.patch"
- patch -Np1 -i "$srcdir/libre.patch"
- patch -Np1 -i "$srcdir/free-distros.patch"
+ # Apply patches
+ for _p in "$srcdir"/*.patch; do
+ [[ -e $_p ]] || continue
+ msg2 "Apply patch ${_p##*/}"
+ patch -Np1 -i "$_p"
+ done
- ## Removing Nonfree directories
+ ## Removing Nonfree directories and Nonfree files
rm -rv "./include/VBox/ExtPack"
rm -rv "./src/VBox/ExtPacks"
rm -rv "./src/VBox/Main/src-helper-apps"
+ rm -rv "./src/VBox/Main/include/ExtPackManagerImpl.h"
+ rm -rv "./src/VBox/Main/include/ExtPackUtil.h"
+ rm -rv "./src/VBox/Main/src-all/ExtPackManagerImpl.cpp"
+ rm -rv "./src/VBox/Main/src-all/ExtPackUtil.cpp"
## Removing Oracle VM VirtualBox Extension Pack icons
rm -v "./src/VBox/Resources/darwin/virtualbox-vbox-extpack.icns"
@@ -148,7 +156,7 @@ build() {
--enable-webservice \
--enable-vde \
--enable-vnc \
- --disable-kmods
+ --disable-kmods
# --with-linux=/usr/src/linux-${_kernver}
source ./env.sh
kmk all
@@ -228,7 +236,7 @@ package_virtualbox-libre() {
echo 'INSTALL_DIR=/usr/lib/virtualbox' > "$pkgdir/etc/vbox/vbox.cfg"
#udev and licence
- install -D -m 0644 "$srcdir/VirtualBox-$pkgver/COPYING" \
+ install -D -m 0644 "$srcdir/VirtualBox-${pkgver}/COPYING" \
"$pkgdir/usr/share/licenses/virtualbox/LICENSE"
install -D -m 0644 "$srcdir/10-vboxdrv.rules" \
"$pkgdir/usr/lib/udev/rules.d/10-vboxdrv.rules"
@@ -333,3 +341,5 @@ package_virtualbox-libre-guest-utils(){
install -D -m644 vboxservice.service \
"$pkgdir/usr/lib/systemd/system/vboxservice.service"
}
+
+# vim:set ts=4 sw=4 et:
diff --git a/libre/virtualbox-libre/gsoap.patch b/libre/virtualbox-libre/gsoap.patch
deleted file mode 100755
index c49caa720..000000000
--- a/libre/virtualbox-libre/gsoap.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- configure.orig 2012-03-14 08:40:02.447527213 +0000
-+++ configure 2012-03-14 09:05:01.535432453 +0000
-@@ -1959,7 +1959,7 @@
- else
- cnf_append "VBOX_GSOAP_CXX_SOURCES" ""
- fi
-- cnf_append "VBOX_GSOAP_CXX_LIBS" "libgsoap++"
-+ cnf_append "VBOX_GSOAP_CXX_LIBS" "libgsoapssl++ libz"
- log_success "found"
- else
- log_failure "stlvector.h not found -- disabling webservice"
diff --git a/libre/virtualbox-libre/ipv6_vnc.patch b/libre/virtualbox-libre/ipv6_vnc.patch
deleted file mode 100755
index 8f50aba1c..000000000
--- a/libre/virtualbox-libre/ipv6_vnc.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-diff -aur vanilla/VirtualBox-4.1.18/src/VBox/Frontends/VBoxHeadless/FramebufferVNC.cpp changed/VirtualBox-4.1.18/src/VBox/Frontends/VBoxHeadless/FramebufferVNC.cpp
---- vanilla/VirtualBox-4.1.18/src/VBox/Frontends/VBoxHeadless/FramebufferVNC.cpp 2012-06-20 15:15:53.000000000 +0200
-+++ changed/VirtualBox-4.1.18/src/VBox/Frontends/VBoxHeadless/FramebufferVNC.cpp 2012-07-16 16:24:22.448349886 +0200
-@@ -88,8 +88,16 @@
-
- vncServer = rfbGetScreen(0, NULL, mWidth, mHeight, 8, 3, 1);
- vncServer->screenData = (void*)this;
-+#ifdef LIBVNCSERVER_IPv6
-+ if (mVncPort) {
-+ vncServer->port = mVncPort;
-+ vncServer->ipv6port = mVncPort;
-+ }
-+#else
- if (mVncPort)
- vncServer->port = mVncPort;
-+#endif
-+
- char *pszDesktopName;
- rc = RTStrAPrintf(&pszDesktopName, "%s - VirtualBox", pszName);
- if (rc >= 0)
diff --git a/libre/virtualbox-libre/libre.patch b/libre/virtualbox-libre/libre.patch
index 41a34fc84..138bbd612 100755
--- a/libre/virtualbox-libre/libre.patch
+++ b/libre/virtualbox-libre/libre.patch
@@ -484,4913 +484,6 @@
extern const PDMDEVREG g_DeviceACPI;
extern const PDMDEVREG g_DeviceDMA;
extern const PDMDEVREG g_DeviceFloppyController;
---- VirtualBox-4.2.0.orig/src/VBox/Main/include/ExtPackManagerImpl.h 2012-03-13 11:51:50.000000000 -0300
-+++ /dev/null 2012-09-18 22:18:48.866734195 -0300
-@@ -1,247 +0,0 @@
--/* $Id: ExtPackManagerImpl.h 39878 2012-01-25 16:30:07Z vboxsync $ */
--/** @file
-- * VirtualBox Main - interface for Extension Packs, VBoxSVC & VBoxC.
-- */
--
--/*
-- * Copyright (C) 2010 Oracle Corporation
-- *
-- * This file is part of VirtualBox Open Source Edition (OSE), as
-- * available from http://www.virtualbox.org. This file is free software;
-- * you can redistribute it and/or modify it under the terms of the GNU
-- * General Public License (GPL) as published by the Free Software
-- * Foundation, in version 2 as it comes in the "COPYING" file of the
-- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-- */
--
--#ifndef ____H_EXTPACKMANAGERIMPL
--#define ____H_EXTPACKMANAGERIMPL
--
--#include "VirtualBoxBase.h"
--#include <VBox/ExtPack/ExtPack.h>
--#include <iprt/fs.h>
--
--/**
-- * An extension pack file.
-- */
--class ATL_NO_VTABLE ExtPackFile :
-- public VirtualBoxBase,
-- VBOX_SCRIPTABLE_IMPL(IExtPackFile)
--{
--public:
-- /** @name COM and internal init/term/mapping cruft.
-- * @{ */
-- VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ExtPackFile, IExtPackFile)
-- DECLARE_NOT_AGGREGATABLE(ExtPackFile)
-- DECLARE_PROTECT_FINAL_CONSTRUCT()
-- BEGIN_COM_MAP(ExtPackFile)
-- VBOX_DEFAULT_INTERFACE_ENTRIES(IExtPackFile)
-- COM_INTERFACE_ENTRY(IExtPackBase)
-- END_COM_MAP()
-- DECLARE_EMPTY_CTOR_DTOR(ExtPackFile)
--
-- HRESULT FinalConstruct();
-- void FinalRelease();
-- HRESULT initWithFile(const char *a_pszFile, const char *a_pszDigest, class ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox);
-- void uninit();
-- RTMEMEF_NEW_AND_DELETE_OPERATORS();
-- /** @} */
--
-- /** @name IExtPackBase interfaces
-- * @{ */
-- STDMETHOD(COMGETTER(Name))(BSTR *a_pbstrName);
-- STDMETHOD(COMGETTER(Description))(BSTR *a_pbstrDescription);
-- STDMETHOD(COMGETTER(Version))(BSTR *a_pbstrVersion);
-- STDMETHOD(COMGETTER(Revision))(ULONG *a_puRevision);
-- STDMETHOD(COMGETTER(Edition))(BSTR *a_pbstrEdition);
-- STDMETHOD(COMGETTER(VRDEModule))(BSTR *a_pbstrVrdeModule);
-- STDMETHOD(COMGETTER(PlugIns))(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns));
-- STDMETHOD(COMGETTER(Usable))(BOOL *a_pfUsable);
-- STDMETHOD(COMGETTER(WhyUnusable))(BSTR *a_pbstrWhy);
-- STDMETHOD(COMGETTER(ShowLicense))(BOOL *a_pfShowIt);
-- STDMETHOD(COMGETTER(License))(BSTR *a_pbstrHtmlLicense);
-- STDMETHOD(QueryLicense)(IN_BSTR a_bstrPreferredLocale, IN_BSTR a_bstrPreferredLanguage,
-- IN_BSTR a_bstrFormat, BSTR *a_pbstrLicense);
-- /** @} */
--
-- /** @name IExtPackFile interfaces
-- * @{ */
-- STDMETHOD(COMGETTER(FilePath))(BSTR *a_pbstrPath);
-- STDMETHOD(Install)(BOOL a_fReplace, IN_BSTR a_bstrDisplayInfo, IProgress **a_ppProgress);
-- /** @} */
--
--private:
-- /** @name Misc init helpers
-- * @{ */
-- HRESULT initFailed(const char *a_pszWhyFmt, ...);
-- /** @} */
--
--private:
-- struct Data;
-- /** Pointer to the private instance. */
-- Data *m;
--
-- friend class ExtPackManager;
--};
--
--
--/**
-- * An installed extension pack.
-- */
--class ATL_NO_VTABLE ExtPack :
-- public VirtualBoxBase,
-- VBOX_SCRIPTABLE_IMPL(IExtPack)
--{
--public:
-- /** @name COM and internal init/term/mapping cruft.
-- * @{ */
-- VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ExtPack, IExtPack)
-- DECLARE_NOT_AGGREGATABLE(ExtPack)
-- DECLARE_PROTECT_FINAL_CONSTRUCT()
-- BEGIN_COM_MAP(ExtPack)
-- VBOX_DEFAULT_INTERFACE_ENTRIES(IExtPack)
-- COM_INTERFACE_ENTRY(IExtPackBase)
-- END_COM_MAP()
-- DECLARE_EMPTY_CTOR_DTOR(ExtPack)
--
-- HRESULT FinalConstruct();
-- void FinalRelease();
-- HRESULT initWithDir(VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir);
-- void uninit();
-- RTMEMEF_NEW_AND_DELETE_OPERATORS();
-- /** @} */
--
-- /** @name IExtPackBase interfaces
-- * @{ */
-- STDMETHOD(COMGETTER(Name))(BSTR *a_pbstrName);
-- STDMETHOD(COMGETTER(Description))(BSTR *a_pbstrDescription);
-- STDMETHOD(COMGETTER(Version))(BSTR *a_pbstrVersion);
-- STDMETHOD(COMGETTER(Revision))(ULONG *a_puRevision);
-- STDMETHOD(COMGETTER(Edition))(BSTR *a_pbstrEdition);
-- STDMETHOD(COMGETTER(VRDEModule))(BSTR *a_pbstrVrdeModule);
-- STDMETHOD(COMGETTER(PlugIns))(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns));
-- STDMETHOD(COMGETTER(Usable))(BOOL *a_pfUsable);
-- STDMETHOD(COMGETTER(WhyUnusable))(BSTR *a_pbstrWhy);
-- STDMETHOD(COMGETTER(ShowLicense))(BOOL *a_pfShowIt);
-- STDMETHOD(COMGETTER(License))(BSTR *a_pbstrHtmlLicense);
-- STDMETHOD(QueryLicense)(IN_BSTR a_bstrPreferredLocale, IN_BSTR a_bstrPreferredLanguage,
-- IN_BSTR a_bstrFormat, BSTR *a_pbstrLicense);
-- /** @} */
--
-- /** @name IExtPack interfaces
-- * @{ */
-- STDMETHOD(QueryObject)(IN_BSTR a_bstrObjectId, IUnknown **a_ppUnknown);
-- /** @} */
--
-- /** @name Internal interfaces used by ExtPackManager.
-- * @{ */
-- bool callInstalledHook(IVirtualBox *a_pVirtualBox, AutoWriteLock *a_pLock, PRTERRINFO pErrInfo);
-- HRESULT callUninstallHookAndClose(IVirtualBox *a_pVirtualBox, bool a_fForcedRemoval);
-- bool callVirtualBoxReadyHook(IVirtualBox *a_pVirtualBox, AutoWriteLock *a_pLock);
-- bool callConsoleReadyHook(IConsole *a_pConsole, AutoWriteLock *a_pLock);
-- bool callVmCreatedHook(IVirtualBox *a_pVirtualBox, IMachine *a_pMachine, AutoWriteLock *a_pLock);
-- bool callVmConfigureVmmHook(IConsole *a_pConsole, PVM a_pVM, AutoWriteLock *a_pLock, int *a_pvrc);
-- bool callVmPowerOnHook(IConsole *a_pConsole, PVM a_pVM, AutoWriteLock *a_pLock, int *a_pvrc);
-- bool callVmPowerOffHook(IConsole *a_pConsole, PVM a_pVM, AutoWriteLock *a_pLock);
-- HRESULT checkVrde(void);
-- HRESULT getVrdpLibraryName(Utf8Str *a_pstrVrdeLibrary);
-- bool wantsToBeDefaultVrde(void) const;
-- HRESULT refresh(bool *pfCanDelete);
-- /** @} */
--
--protected:
-- /** @name Internal helper methods.
-- * @{ */
-- void probeAndLoad(void);
-- bool findModule(const char *a_pszName, const char *a_pszExt, VBOXEXTPACKMODKIND a_enmKind,
-- Utf8Str *a_ppStrFound, bool *a_pfNative, PRTFSOBJINFO a_pObjInfo) const;
-- static bool objinfoIsEqual(PCRTFSOBJINFO pObjInfo1, PCRTFSOBJINFO pObjInfo2);
-- /** @} */
--
-- /** @name Extension Pack Helpers
-- * @{ */
-- static DECLCALLBACK(int) hlpFindModule(PCVBOXEXTPACKHLP pHlp, const char *pszName, const char *pszExt,
-- VBOXEXTPACKMODKIND enmKind, char *pszFound, size_t cbFound, bool *pfNative);
-- static DECLCALLBACK(int) hlpGetFilePath(PCVBOXEXTPACKHLP pHlp, const char *pszFilename, char *pszPath, size_t cbPath);
-- static DECLCALLBACK(VBOXEXTPACKCTX) hlpGetContext(PCVBOXEXTPACKHLP pHlp);
-- static DECLCALLBACK(int) hlpReservedN(PCVBOXEXTPACKHLP pHlp);
-- /** @} */
--
--private:
-- struct Data;
-- /** Pointer to the private instance. */
-- Data *m;
--
-- friend class ExtPackManager;
--};
--
--
--/**
-- * Extension pack manager.
-- */
--class ATL_NO_VTABLE ExtPackManager :
-- public VirtualBoxBase,
-- VBOX_SCRIPTABLE_IMPL(IExtPackManager)
--{
-- /** @name COM and internal init/term/mapping cruft.
-- * @{ */
-- VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ExtPackManager, IExtPackManager)
-- DECLARE_NOT_AGGREGATABLE(ExtPackManager)
-- DECLARE_PROTECT_FINAL_CONSTRUCT()
-- BEGIN_COM_MAP(ExtPackManager)
-- VBOX_DEFAULT_INTERFACE_ENTRIES(IExtPackManager)
-- END_COM_MAP()
-- DECLARE_EMPTY_CTOR_DTOR(ExtPackManager)
--
-- HRESULT FinalConstruct();
-- void FinalRelease();
-- HRESULT initExtPackManager(VirtualBox *a_pVirtualBox, VBOXEXTPACKCTX a_enmContext);
-- void uninit();
-- RTMEMEF_NEW_AND_DELETE_OPERATORS();
-- /** @} */
--
-- /** @name IExtPack interfaces
-- * @{ */
-- STDMETHOD(COMGETTER(InstalledExtPacks))(ComSafeArrayOut(IExtPack *, a_paExtPacks));
-- STDMETHOD(Find)(IN_BSTR a_bstrName, IExtPack **a_pExtPack);
-- STDMETHOD(OpenExtPackFile)(IN_BSTR a_bstrTarball, IExtPackFile **a_ppExtPackFile);
-- STDMETHOD(Uninstall)(IN_BSTR a_bstrName, BOOL a_fForcedRemoval, IN_BSTR a_bstrDisplayInfo, IProgress **a_ppProgress);
-- STDMETHOD(Cleanup)(void);
-- STDMETHOD(QueryAllPlugInsForFrontend)(IN_BSTR a_bstrFrontend, ComSafeArrayOut(BSTR, a_pabstrPlugInModules));
-- STDMETHOD(IsExtPackUsable(IN_BSTR a_bstrExtPack, BOOL *aUsable));
-- /** @} */
--
-- /** @name Internal interfaces used by other Main classes.
-- * @{ */
-- static DECLCALLBACK(int) doInstallThreadProc(RTTHREAD hThread, void *pvJob);
-- HRESULT doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo);
-- static DECLCALLBACK(int) doUninstallThreadProc(RTTHREAD hThread, void *pvJob);
-- HRESULT doUninstall(const Utf8Str *a_pstrName, bool a_fForcedRemoval, const Utf8Str *a_pstrDisplayInfo);
-- void callAllVirtualBoxReadyHooks(void);
-- void callAllConsoleReadyHooks(IConsole *a_pConsole);
-- void callAllVmCreatedHooks(IMachine *a_pMachine);
-- int callAllVmConfigureVmmHooks(IConsole *a_pConsole, PVM a_pVM);
-- int callAllVmPowerOnHooks(IConsole *a_pConsole, PVM a_pVM);
-- void callAllVmPowerOffHooks(IConsole *a_pConsole, PVM a_pVM);
-- HRESULT checkVrdeExtPack(Utf8Str const *a_pstrExtPack);
-- int getVrdeLibraryPathForExtPack(Utf8Str const *a_pstrExtPack, Utf8Str *a_pstrVrdeLibrary);
-- HRESULT getDefaultVrdeExtPack(Utf8Str *a_pstrExtPack);
-- bool isExtPackUsable(const char *a_pszExtPack);
-- void dumpAllToReleaseLog(void);
-- /** @} */
--
--private:
-- HRESULT runSetUidToRootHelper(Utf8Str const *a_pstrDisplayInfo, const char *a_pszCommand, ...);
-- ExtPack *findExtPack(const char *a_pszName);
-- void removeExtPack(const char *a_pszName);
-- HRESULT refreshExtPack(const char *a_pszName, bool a_fUnsuableIsError, ExtPack **a_ppExtPack);
--
--private:
-- struct Data;
-- /** Pointer to the private instance. */
-- Data *m;
--};
--
--#endif
--/* vi: set tabstop=4 shiftwidth=4 expandtab: */
---- VirtualBox-4.2.0.orig/src/VBox/Main/include/ExtPackUtil.h 2012-03-13 11:51:50.000000000 -0300
-+++ /dev/null 2012-09-18 22:18:48.866734195 -0300
-@@ -1,137 +0,0 @@
--/* $Id: ExtPackUtil.h 39878 2012-01-25 16:30:07Z vboxsync $ */
--/** @file
-- * VirtualBox Main - Extension Pack Utilities and definitions, VBoxC, VBoxSVC, ++.
-- */
--
--/*
-- * Copyright (C) 2010 Oracle Corporation
-- *
-- * This file is part of VirtualBox Open Source Edition (OSE), as
-- * available from http://www.virtualbox.org. This file is free software;
-- * you can redistribute it and/or modify it under the terms of the GNU
-- * General Public License (GPL) as published by the Free Software
-- * Foundation, in version 2 as it comes in the "COPYING" file of the
-- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-- */
--
--#ifndef ____H_EXTPACKUTIL
--#define ____H_EXTPACKUTIL
--
--#include <iprt/cpp/ministring.h>
--#include <iprt/fs.h>
--#include <iprt/vfs.h>
--
--
--/** @name VBOX_EXTPACK_DESCRIPTION_NAME
-- * The name of the description file in an extension pack. */
--#define VBOX_EXTPACK_DESCRIPTION_NAME "ExtPack.xml"
--/** @name VBOX_EXTPACK_DESCRIPTION_NAME
-- * The name of the manifest file in an extension pack. */
--#define VBOX_EXTPACK_MANIFEST_NAME "ExtPack.manifest"
--/** @name VBOX_EXTPACK_SIGNATURE_NAME
-- * The name of the signature file in an extension pack. */
--#define VBOX_EXTPACK_SIGNATURE_NAME "ExtPack.signature"
--/** @name VBOX_EXTPACK_LICENSE_NAME_PREFIX
-- * The name prefix of a license file in an extension pack. There can be
-- * several license files in a pack, the variations being on locale, language
-- * and format (HTML, RTF, plain text). All extension packages shall include
-- * a */
--#define VBOX_EXTPACK_LICENSE_NAME_PREFIX "ExtPack-license"
--/** @name VBOX_EXTPACK_SUFFIX
-- * The suffix of a extension pack tarball. */
--#define VBOX_EXTPACK_SUFFIX ".vbox-extpack"
--
--/** The minimum length (strlen) of a extension pack name. */
--#define VBOX_EXTPACK_NAME_MIN_LEN 3
--/** The max length (strlen) of a extension pack name. */
--#define VBOX_EXTPACK_NAME_MAX_LEN 64
--
--/** The architecture-dependent application data subdirectory where the
-- * extension packs are installed. Relative to RTPathAppPrivateArch. */
--#define VBOX_EXTPACK_INSTALL_DIR "ExtensionPacks"
--/** The architecture-independent application data subdirectory where the
-- * certificates are installed. Relative to RTPathAppPrivateNoArch. */
--#define VBOX_EXTPACK_CERT_DIR "ExtPackCertificates"
--
--/** The maximum entry name length.
-- * Play short and safe. */
--#define VBOX_EXTPACK_MAX_MEMBER_NAME_LENGTH 128
--
--
--/**
-- * Plug-in descriptor.
-- */
--typedef struct VBOXEXTPACKPLUGINDESC
--{
-- /** The name. */
-- RTCString strName;
-- /** The module name. */
-- RTCString strModule;
-- /** The description. */
-- RTCString strDescription;
-- /** The frontend or component which it plugs into. */
-- RTCString strFrontend;
--} VBOXEXTPACKPLUGINDESC;
--/** Pointer to a plug-in descriptor. */
--typedef VBOXEXTPACKPLUGINDESC *PVBOXEXTPACKPLUGINDESC;
--
--/**
-- * Extension pack descriptor
-- *
-- * This is the internal representation of the ExtPack.xml.
-- */
--typedef struct VBOXEXTPACKDESC
--{
-- /** The name. */
-- RTCString strName;
-- /** The description. */
-- RTCString strDescription;
-- /** The version string. */
-- RTCString strVersion;
-- /** The edition string. */
-- RTCString strEdition;
-- /** The internal revision number. */
-- uint32_t uRevision;
-- /** The name of the main module. */
-- RTCString strMainModule;
-- /** The name of the VRDE module, empty if none. */
-- RTCString strVrdeModule;
-- /** The number of plug-in descriptors. */
-- uint32_t cPlugIns;
-- /** Pointer to an array of plug-in descriptors. */
-- PVBOXEXTPACKPLUGINDESC paPlugIns;
-- /** Whether to show the license prior to installation. */
-- bool fShowLicense;
--} VBOXEXTPACKDESC;
--
--/** Pointer to a extension pack descriptor. */
--typedef VBOXEXTPACKDESC *PVBOXEXTPACKDESC;
--/** Pointer to a const extension pack descriptor. */
--typedef VBOXEXTPACKDESC const *PCVBOXEXTPACKDESC;
--
--
--void VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc);
--RTCString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
--RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
--RTCString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball);
--void VBoxExtPackFreeDesc(PVBOXEXTPACKDESC a_pExtPackDesc);
--bool VBoxExtPackIsValidName(const char *pszName);
--bool VBoxExtPackIsValidMangledName(const char *pszMangledName, size_t cchMax = RTSTR_MAX);
--RTCString *VBoxExtPackMangleName(const char *pszName);
--RTCString *VBoxExtPackUnmangleName(const char *pszMangledName, size_t cbMax);
--int VBoxExtPackCalcDir(char *pszExtPackDir, size_t cbExtPackDir, const char *pszParentDir, const char *pszName);
--bool VBoxExtPackIsValidVersionString(const char *pszVersion);
--bool VBoxExtPackIsValidEditionString(const char *pszEdition);
--bool VBoxExtPackIsValidModuleString(const char *pszModule);
--
--int VBoxExtPackValidateMember(const char *pszName, RTVFSOBJTYPE enmType, RTVFSOBJ hVfsObj, char *pszError, size_t cbError);
--int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss, PRTMANIFEST phFileManifest);
--int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName,
-- const char *pszTarball, const char *pszTarballDigest,
-- char *pszError, size_t cbError,
-- PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile, RTCString *pStrDigest);
--
--
--#endif
--
---- VirtualBox-4.2.0.orig/src/VBox/Main/src-all/ExtPackManagerImpl.cpp 2012-04-03 04:56:24.000000000 -0300
-+++ /dev/null 2012-09-18 22:18:48.866734195 -0300
-@@ -1,3126 +0,0 @@
--/* $Id: ExtPackManagerImpl.cpp 40468 2012-03-14 17:07:58Z vboxsync $ */
--/** @file
-- * VirtualBox Main - interface for Extension Packs, VBoxSVC & VBoxC.
-- */
--
--/*
-- * Copyright (C) 2010 Oracle Corporation
-- *
-- * This file is part of VirtualBox Open Source Edition (OSE), as
-- * available from http://www.virtualbox.org. This file is free software;
-- * you can redistribute it and/or modify it under the terms of the GNU
-- * General Public License (GPL) as published by the Free Software
-- * Foundation, in version 2 as it comes in the "COPYING" file of the
-- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-- */
--
--
--/*******************************************************************************
--* Header Files *
--*******************************************************************************/
--#include "ExtPackManagerImpl.h"
--#include "ExtPackUtil.h"
--
--#include <iprt/buildconfig.h>
--#include <iprt/ctype.h>
--#include <iprt/dir.h>
--#include <iprt/env.h>
--#include <iprt/file.h>
--#include <iprt/ldr.h>
--#include <iprt/manifest.h>
--#include <iprt/param.h>
--#include <iprt/path.h>
--#include <iprt/pipe.h>
--#include <iprt/process.h>
--#include <iprt/string.h>
--
--#include <VBox/com/array.h>
--#include <VBox/com/ErrorInfo.h>
--#include <VBox/err.h>
--#include <VBox/log.h>
--#include <VBox/sup.h>
--#include <VBox/version.h>
--#include "AutoCaller.h"
--#include "Global.h"
--#include "ProgressImpl.h"
--#include "SystemPropertiesImpl.h"
--#include "VirtualBoxImpl.h"
--
--
--/*******************************************************************************
--* Defined Constants And Macros *
--*******************************************************************************/
--/** @name VBOX_EXTPACK_HELPER_NAME
-- * The name of the utility application we employ to install and uninstall the
-- * extension packs. This is a set-uid-to-root binary on unixy platforms, which
-- * is why it has to be a separate application.
-- */
--#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
--# define VBOX_EXTPACK_HELPER_NAME "VBoxExtPackHelperApp.exe"
--#else
--# define VBOX_EXTPACK_HELPER_NAME "VBoxExtPackHelperApp"
--#endif
--
--
--/*******************************************************************************
--* Structures and Typedefs *
--*******************************************************************************/
--struct ExtPackBaseData
--{
--public:
-- /** The extension pack descriptor (loaded from the XML, mostly). */
-- VBOXEXTPACKDESC Desc;
-- /** The file system object info of the XML file.
-- * This is for detecting changes and save time in refresh(). */
-- RTFSOBJINFO ObjInfoDesc;
-- /** Whether it's usable or not. */
-- bool fUsable;
-- /** Why it is unusable. */
-- Utf8Str strWhyUnusable;
--};
--
--/**
-- * Private extension pack data.
-- */
--struct ExtPackFile::Data : public ExtPackBaseData
--{
--public:
-- /** The path to the tarball. */
-- Utf8Str strExtPackFile;
-- /** The SHA-256 hash of the file (as string). */
-- Utf8Str strDigest;
-- /** The file handle of the extension pack file. */
-- RTFILE hExtPackFile;
-- /** Our manifest for the tarball. */
-- RTMANIFEST hOurManifest;
-- /** Pointer to the extension pack manager. */
-- ComObjPtr<ExtPackManager> ptrExtPackMgr;
-- /** Pointer to the VirtualBox object so we can create a progress object. */
-- VirtualBox *pVirtualBox;
--
-- RTMEMEF_NEW_AND_DELETE_OPERATORS();
--};
--
--/**
-- * Private extension pack data.
-- */
--struct ExtPack::Data : public ExtPackBaseData
--{
--public:
-- /** Where the extension pack is located. */
-- Utf8Str strExtPackPath;
-- /** The file system object info of the extension pack directory.
-- * This is for detecting changes and save time in refresh(). */
-- RTFSOBJINFO ObjInfoExtPack;
-- /** The full path to the main module. */
-- Utf8Str strMainModPath;
-- /** The file system object info of the main module.
-- * This is used to determin whether to bother try reload it. */
-- RTFSOBJINFO ObjInfoMainMod;
-- /** The module handle of the main extension pack module. */
-- RTLDRMOD hMainMod;
--
-- /** The helper callbacks for the extension pack. */
-- VBOXEXTPACKHLP Hlp;
-- /** Pointer back to the extension pack object (for Hlp methods). */
-- ExtPack *pThis;
-- /** The extension pack registration structure. */
-- PCVBOXEXTPACKREG pReg;
-- /** The current context. */
-- VBOXEXTPACKCTX enmContext;
-- /** Set if we've made the pfnVirtualBoxReady or pfnConsoleReady call. */
-- bool fMadeReadyCall;
--
-- RTMEMEF_NEW_AND_DELETE_OPERATORS();
--};
--
--/** List of extension packs. */
--typedef std::list< ComObjPtr<ExtPack> > ExtPackList;
--
--/**
-- * Private extension pack manager data.
-- */
--struct ExtPackManager::Data
--{
-- /** The directory where the extension packs are installed. */
-- Utf8Str strBaseDir;
-- /** The directory where the certificates this installation recognizes are
-- * stored. */
-- Utf8Str strCertificatDirPath;
-- /** The list of installed extension packs. */
-- ExtPackList llInstalledExtPacks;
-- /** Pointer to the VirtualBox object, our parent. */
-- VirtualBox *pVirtualBox;
-- /** The current context. */
-- VBOXEXTPACKCTX enmContext;
--#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_DARWIN)
-- /** File handle for the VBoxVMM libary which we slurp because ExtPacks depend on it. */
-- RTLDRMOD hVBoxVMM;
--#endif
--
-- RTMEMEF_NEW_AND_DELETE_OPERATORS();
--};
--
--/**
-- * Extension pack installation job.
-- */
--typedef struct EXTPACKINSTALLJOB
--{
-- /** Smart pointer to the extension pack file. */
-- ComPtr<ExtPackFile> ptrExtPackFile;
-- /** The replace argument. */
-- bool fReplace;
-- /** The display info argument. */
-- Utf8Str strDisplayInfo;
-- /** Smart pointer to the extension manager. */
-- ComPtr<ExtPackManager> ptrExtPackMgr;
-- /** Smart pointer to the progress object for this job. */
-- ComObjPtr<Progress> ptrProgress;
--} EXTPACKINSTALLJOB;
--/** Pointer to an extension pack installation job. */
--typedef EXTPACKINSTALLJOB *PEXTPACKINSTALLJOB;
--
--/**
-- * Extension pack uninstallation job.
-- */
--typedef struct EXTPACKUNINSTALLJOB
--{
-- /** Smart pointer to the extension manager. */
-- ComPtr<ExtPackManager> ptrExtPackMgr;
-- /** The name of the extension pack. */
-- Utf8Str strName;
-- /** The replace argument. */
-- bool fForcedRemoval;
-- /** The display info argument. */
-- Utf8Str strDisplayInfo;
-- /** Smart pointer to the progress object for this job. */
-- ComObjPtr<Progress> ptrProgress;
--} EXTPACKUNINSTALLJOB;
--/** Pointer to an extension pack uninstallation job. */
--typedef EXTPACKUNINSTALLJOB *PEXTPACKUNINSTALLJOB;
--
--
--DEFINE_EMPTY_CTOR_DTOR(ExtPackFile)
--
--/**
-- * Called by ComObjPtr::createObject when creating the object.
-- *
-- * Just initialize the basic object state, do the rest in initWithDir().
-- *
-- * @returns S_OK.
-- */
--HRESULT ExtPackFile::FinalConstruct()
--{
-- m = NULL;
-- return BaseFinalConstruct();
--}
--
--/**
-- * Initializes the extension pack by reading its file.
-- *
-- * @returns COM status code.
-- * @param a_pszFile The path to the extension pack file.
-- * @param a_pszDigest The SHA-256 digest of the file. Or an empty string.
-- * @param a_pExtPackMgr Pointer to the extension pack manager.
-- * @param a_pVirtualBox Pointer to the VirtualBox object.
-- */
--HRESULT ExtPackFile::initWithFile(const char *a_pszFile, const char *a_pszDigest, ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox)
--{
-- AutoInitSpan autoInitSpan(this);
-- AssertReturn(autoInitSpan.isOk(), E_FAIL);
--
-- /*
-- * Allocate + initialize our private data.
-- */
-- m = new ExtPackFile::Data;
-- VBoxExtPackInitDesc(&m->Desc);
-- RT_ZERO(m->ObjInfoDesc);
-- m->fUsable = false;
-- m->strWhyUnusable = tr("ExtPack::init failed");
-- m->strExtPackFile = a_pszFile;
-- m->strDigest = a_pszDigest;
-- m->hExtPackFile = NIL_RTFILE;
-- m->hOurManifest = NIL_RTMANIFEST;
-- m->ptrExtPackMgr = a_pExtPackMgr;
-- m->pVirtualBox = a_pVirtualBox;
--
-- RTCString *pstrTarName = VBoxExtPackExtractNameFromTarballPath(a_pszFile);
-- if (pstrTarName)
-- {
-- m->Desc.strName = *pstrTarName;
-- delete pstrTarName;
-- pstrTarName = NULL;
-- }
--
-- autoInitSpan.setSucceeded();
--
-- /*
-- * Try open the extension pack and check that it is a regular file.
-- */
-- int vrc = RTFileOpen(&m->hExtPackFile, a_pszFile,
-- RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN);
-- if (RT_FAILURE(vrc))
-- {
-- if (vrc == VERR_FILE_NOT_FOUND || vrc == VERR_PATH_NOT_FOUND)
-- return initFailed(tr("'%s' file not found"), a_pszFile);
-- return initFailed(tr("RTFileOpen('%s',,) failed with %Rrc"), a_pszFile, vrc);
-- }
--
-- RTFSOBJINFO ObjInfo;
-- vrc = RTFileQueryInfo(m->hExtPackFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
-- if (RT_FAILURE(vrc))
-- return initFailed(tr("RTFileQueryInfo failed with %Rrc on '%s'"), vrc, a_pszFile);
-- if (!RTFS_IS_FILE(ObjInfo.Attr.fMode))
-- return initFailed(tr("Not a regular file: %s"), a_pszFile);
--
-- /*
-- * Validate the tarball and extract the XML file.
-- */
-- char szError[8192];
-- RTVFSFILE hXmlFile;
-- vrc = VBoxExtPackValidateTarball(m->hExtPackFile, NULL /*pszExtPackName*/, a_pszFile, a_pszDigest,
-- szError, sizeof(szError), &m->hOurManifest, &hXmlFile, &m->strDigest);
-- if (RT_FAILURE(vrc))
-- return initFailed(tr("%s"), szError);
--
-- /*
-- * Parse the XML.
-- */
-- RTCString strSavedName(m->Desc.strName);
-- RTCString *pStrLoadErr = VBoxExtPackLoadDescFromVfsFile(hXmlFile, &m->Desc, &m->ObjInfoDesc);
-- RTVfsFileRelease(hXmlFile);
-- if (pStrLoadErr != NULL)
-- {
-- m->strWhyUnusable.printf(tr("Failed to the xml file: %s"), pStrLoadErr->c_str());
-- m->Desc.strName = strSavedName;
-- delete pStrLoadErr;
-- return S_OK;
-- }
--
-- /*
-- * Match the tarball name with the name from the XML.
-- */
-- /** @todo drop this restriction after the old install interface is
-- * dropped. */
-- if (!strSavedName.equalsIgnoreCase(m->Desc.strName))
-- return initFailed(tr("Extension pack name mismatch between the downloaded file and the XML inside it (xml='%s' file='%s')"),
-- m->Desc.strName.c_str(), strSavedName.c_str());
--
-- m->fUsable = true;
-- m->strWhyUnusable.setNull();
-- return S_OK;
--}
--
--/**
-- * Protected helper that formats the strWhyUnusable value.
-- *
-- * @returns S_OK
-- * @param a_pszWhyFmt Why it failed, format string.
-- * @param ... The format arguments.
-- */
--HRESULT ExtPackFile::initFailed(const char *a_pszWhyFmt, ...)
--{
-- va_list va;
-- va_start(va, a_pszWhyFmt);
-- m->strWhyUnusable.printfV(a_pszWhyFmt, va);
-- va_end(va);
-- return S_OK;
--}
--
--/**
-- * COM cruft.
-- */
--void ExtPackFile::FinalRelease()
--{
-- uninit();
-- BaseFinalRelease();
--}
--
--/**
-- * Do the actual cleanup.
-- */
--void ExtPackFile::uninit()
--{
-- /* Enclose the state transition Ready->InUninit->NotReady */
-- AutoUninitSpan autoUninitSpan(this);
-- if (!autoUninitSpan.uninitDone() && m != NULL)
-- {
-- VBoxExtPackFreeDesc(&m->Desc);
-- RTFileClose(m->hExtPackFile);
-- m->hExtPackFile = NIL_RTFILE;
-- RTManifestRelease(m->hOurManifest);
-- m->hOurManifest = NIL_RTMANIFEST;
--
-- delete m;
-- m = NULL;
-- }
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(Name)(BSTR *a_pbstrName)
--{
-- CheckComArgOutPointerValid(a_pbstrName);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strName);
-- str.cloneTo(a_pbstrName);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(Description)(BSTR *a_pbstrDescription)
--{
-- CheckComArgOutPointerValid(a_pbstrDescription);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strDescription);
-- str.cloneTo(a_pbstrDescription);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(Version)(BSTR *a_pbstrVersion)
--{
-- CheckComArgOutPointerValid(a_pbstrVersion);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strVersion);
-- str.cloneTo(a_pbstrVersion);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(Edition)(BSTR *a_pbstrEdition)
--{
-- CheckComArgOutPointerValid(a_pbstrEdition);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strEdition);
-- str.cloneTo(a_pbstrEdition);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(Revision)(ULONG *a_puRevision)
--{
-- CheckComArgOutPointerValid(a_puRevision);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- *a_puRevision = m->Desc.uRevision;
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(VRDEModule)(BSTR *a_pbstrVrdeModule)
--{
-- CheckComArgOutPointerValid(a_pbstrVrdeModule);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strVrdeModule);
-- str.cloneTo(a_pbstrVrdeModule);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(PlugIns)(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns))
--{
-- /** @todo implement plug-ins. */
--#ifdef VBOX_WITH_XPCOM
-- NOREF(a_paPlugIns);
-- NOREF(a_paPlugInsSize);
--#endif
-- ReturnComNotImplemented();
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(Usable)(BOOL *a_pfUsable)
--{
-- CheckComArgOutPointerValid(a_pfUsable);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- *a_pfUsable = m->fUsable;
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(WhyUnusable)(BSTR *a_pbstrWhy)
--{
-- CheckComArgOutPointerValid(a_pbstrWhy);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- m->strWhyUnusable.cloneTo(a_pbstrWhy);
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(ShowLicense)(BOOL *a_pfShowIt)
--{
-- CheckComArgOutPointerValid(a_pfShowIt);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- *a_pfShowIt = m->Desc.fShowLicense;
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(License)(BSTR *a_pbstrHtmlLicense)
--{
-- Bstr bstrHtml("html");
-- return QueryLicense(Bstr::Empty.raw(), Bstr::Empty.raw(), bstrHtml.raw(), a_pbstrHtmlLicense);
--}
--
--/* Same as ExtPack::QueryLicense, should really explore the subject of base classes here... */
--STDMETHODIMP ExtPackFile::QueryLicense(IN_BSTR a_bstrPreferredLocale, IN_BSTR a_bstrPreferredLanguage, IN_BSTR a_bstrFormat,
-- BSTR *a_pbstrLicense)
--{
-- /*
-- * Validate input.
-- */
-- CheckComArgOutPointerValid(a_pbstrLicense);
-- CheckComArgNotNull(a_bstrPreferredLocale);
-- CheckComArgNotNull(a_bstrPreferredLanguage);
-- CheckComArgNotNull(a_bstrFormat);
--
-- Utf8Str strPreferredLocale(a_bstrPreferredLocale);
-- if (strPreferredLocale.length() != 2 && strPreferredLocale.length() != 0)
-- return setError(E_FAIL, tr("The preferred locale is a two character string or empty."));
--
-- Utf8Str strPreferredLanguage(a_bstrPreferredLanguage);
-- if (strPreferredLanguage.length() != 2 && strPreferredLanguage.length() != 0)
-- return setError(E_FAIL, tr("The preferred lanuage is a two character string or empty."));
--
-- Utf8Str strFormat(a_bstrFormat);
-- if ( !strFormat.equals("html")
-- && !strFormat.equals("rtf")
-- && !strFormat.equals("txt"))
-- return setError(E_FAIL, tr("The license format can only have the values 'html', 'rtf' and 'txt'."));
--
-- /*
-- * Combine the options to form a file name before locking down anything.
-- */
-- char szName[sizeof(VBOX_EXTPACK_LICENSE_NAME_PREFIX "-de_DE.html") + 2];
-- if (strPreferredLocale.isNotEmpty() && strPreferredLanguage.isNotEmpty())
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX "-%s_%s.%s",
-- strPreferredLocale.c_str(), strPreferredLanguage.c_str(), strFormat.c_str());
-- else if (strPreferredLocale.isNotEmpty())
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX "-%s.%s", strPreferredLocale.c_str(), strFormat.c_str());
-- else if (strPreferredLanguage.isNotEmpty())
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX "-_%s.%s", strPreferredLocale.c_str(), strFormat.c_str());
-- else
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX ".%s", strFormat.c_str());
--
-- /*
-- * Lock the extension pack. We need a write lock here as there must not be
-- * concurrent accesses to the tar file handle.
-- */
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- /*
-- * Do not permit this query on a pack that isn't considered usable (could
-- * be marked so because of bad license files).
-- */
-- if (!m->fUsable)
-- hrc = setError(E_FAIL, tr("%s"), m->strWhyUnusable.c_str());
-- else
-- {
-- /*
-- * Look it up in the manifest before scanning the tarball for it
-- */
-- if (RTManifestEntryExists(m->hOurManifest, szName))
-- {
-- RTVFSFSSTREAM hTarFss;
-- char szError[8192];
-- int vrc = VBoxExtPackOpenTarFss(m->hExtPackFile, szError, sizeof(szError), &hTarFss, NULL);
-- if (RT_SUCCESS(vrc))
-- {
-- for (;;)
-- {
-- /* Get the first/next. */
-- char *pszName;
-- RTVFSOBJ hVfsObj;
-- RTVFSOBJTYPE enmType;
-- vrc = RTVfsFsStrmNext(hTarFss, &pszName, &enmType, &hVfsObj);
-- if (RT_FAILURE(vrc))
-- {
-- if (vrc != VERR_EOF)
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("RTVfsFsStrmNext failed: %Rrc"), vrc);
-- else
-- hrc = setError(E_UNEXPECTED, tr("'%s' was found in the manifest but not in the tarball"), szName);
-- break;
-- }
--
-- /* Is this it? */
-- const char *pszAdjName = pszName[0] == '.' && pszName[1] == '/' ? &pszName[2] : pszName;
-- if ( !strcmp(pszAdjName, szName)
-- && ( enmType == RTVFSOBJTYPE_IO_STREAM
-- || enmType == RTVFSOBJTYPE_FILE))
-- {
-- RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(hVfsObj);
-- RTVfsObjRelease(hVfsObj);
-- RTStrFree(pszName);
--
-- /* Load the file into memory. */
-- RTFSOBJINFO ObjInfo;
-- vrc = RTVfsIoStrmQueryInfo(hVfsIos, &ObjInfo, RTFSOBJATTRADD_NOTHING);
-- if (RT_SUCCESS(vrc))
-- {
-- size_t cbFile = (size_t)ObjInfo.cbObject;
-- void *pvFile = RTMemAllocZ(cbFile + 1);
-- if (pvFile)
-- {
-- vrc = RTVfsIoStrmRead(hVfsIos, pvFile, cbFile, true /*fBlocking*/, NULL);
-- if (RT_SUCCESS(vrc))
-- {
-- /* try translate it into a string we can return. */
-- Bstr bstrLicense((const char *)pvFile, cbFile);
-- if (bstrLicense.isNotEmpty())
-- {
-- bstrLicense.detachTo(a_pbstrLicense);
-- hrc = S_OK;
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR,
-- tr("The license file '%s' is empty or contains invalid UTF-8 encoding"),
-- szName);
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to read '%s': %Rrc"), szName, vrc);
-- RTMemFree(pvFile);
-- }
-- else
-- hrc = setError(E_OUTOFMEMORY, tr("Failed to allocate %zu bytes for '%s'"), cbFile, szName);
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("RTVfsIoStrmQueryInfo on '%s': %Rrc"), szName, vrc);
-- RTVfsIoStrmRelease(hVfsIos);
-- break;
-- }
--
-- /* Release current. */
-- RTVfsObjRelease(hVfsObj);
-- RTStrFree(pszName);
-- }
-- RTVfsFsStrmRelease(hTarFss);
-- }
-- else
-- hrc = setError(VBOX_E_OBJECT_NOT_FOUND, tr("%s"), szError);
-- }
-- else
-- hrc = setError(VBOX_E_OBJECT_NOT_FOUND, tr("The license file '%s' was not found in '%s'"),
-- szName, m->strExtPackFile.c_str());
-- }
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::COMGETTER(FilePath)(BSTR *a_pbstrPath)
--{
-- CheckComArgOutPointerValid(a_pbstrPath);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- m->strExtPackFile.cloneTo(a_pbstrPath);
-- return hrc;
--}
--
--STDMETHODIMP ExtPackFile::Install(BOOL a_fReplace, IN_BSTR a_bstrDisplayInfo, IProgress **a_ppProgress)
--{
-- if (a_ppProgress)
-- *a_ppProgress = NULL;
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- if (m->fUsable)
-- {
-- PEXTPACKINSTALLJOB pJob = NULL;
-- try
-- {
-- pJob = new EXTPACKINSTALLJOB;
-- pJob->ptrExtPackFile = this;
-- pJob->fReplace = a_fReplace != FALSE;
-- pJob->strDisplayInfo = a_bstrDisplayInfo;
-- pJob->ptrExtPackMgr = m->ptrExtPackMgr;
-- hrc = pJob->ptrProgress.createObject();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr bstrDescription = tr("Installing extension pack");
-- hrc = pJob->ptrProgress->init(
--#ifndef VBOX_COM_INPROC
-- m->pVirtualBox,
--#endif
-- static_cast<IExtPackFile *>(this),
-- bstrDescription.raw(),
-- FALSE /*aCancelable*/,
-- NULL /*aId*/);
-- }
-- if (SUCCEEDED(hrc))
-- {
-- ComPtr<Progress> ptrProgress = pJob->ptrProgress;
-- int vrc = RTThreadCreate(NULL /*phThread*/, ExtPackManager::doInstallThreadProc, pJob, 0,
-- RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ExtPackInst");
-- if (RT_SUCCESS(vrc))
-- {
-- pJob = NULL; /* the thread deletes it */
-- ptrProgress.queryInterfaceTo(a_ppProgress);
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("RTThreadCreate failed with %Rrc"), vrc);
-- }
-- }
-- catch (std::bad_alloc)
-- {
-- hrc = E_OUTOFMEMORY;
-- }
-- if (pJob)
-- delete pJob;
-- }
-- else
-- hrc = setError(E_FAIL, "%s", m->strWhyUnusable.c_str());
-- }
-- return hrc;
--}
--
--
--
--
--
--DEFINE_EMPTY_CTOR_DTOR(ExtPack)
--
--/**
-- * Called by ComObjPtr::createObject when creating the object.
-- *
-- * Just initialize the basic object state, do the rest in initWithDir().
-- *
-- * @returns S_OK.
-- */
--HRESULT ExtPack::FinalConstruct()
--{
-- m = NULL;
-- return S_OK;
--}
--
--/**
-- * Initializes the extension pack by reading its file.
-- *
-- * @returns COM status code.
-- * @param a_enmContext The context we're in.
-- * @param a_pszName The name of the extension pack. This is also the
-- * name of the subdirector under @a a_pszParentDir
-- * where the extension pack is installed.
-- * @param a_pszDir The extension pack directory name.
-- */
--HRESULT ExtPack::initWithDir(VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir)
--{
-- AutoInitSpan autoInitSpan(this);
-- AssertReturn(autoInitSpan.isOk(), E_FAIL);
--
-- static const VBOXEXTPACKHLP s_HlpTmpl =
-- {
-- /* u32Version = */ VBOXEXTPACKHLP_VERSION,
-- /* uVBoxFullVersion = */ VBOX_FULL_VERSION,
-- /* uVBoxVersionRevision = */ 0,
-- /* u32Padding = */ 0,
-- /* pszVBoxVersion = */ "",
-- /* pfnFindModule = */ ExtPack::hlpFindModule,
-- /* pfnGetFilePath = */ ExtPack::hlpGetFilePath,
-- /* pfnGetContext = */ ExtPack::hlpGetContext,
-- /* pfnReserved1 = */ ExtPack::hlpReservedN,
-- /* pfnReserved2 = */ ExtPack::hlpReservedN,
-- /* pfnReserved3 = */ ExtPack::hlpReservedN,
-- /* pfnReserved4 = */ ExtPack::hlpReservedN,
-- /* pfnReserved5 = */ ExtPack::hlpReservedN,
-- /* pfnReserved6 = */ ExtPack::hlpReservedN,
-- /* pfnReserved7 = */ ExtPack::hlpReservedN,
-- /* pfnReserved8 = */ ExtPack::hlpReservedN,
-- /* pfnReserved9 = */ ExtPack::hlpReservedN,
-- /* u32EndMarker = */ VBOXEXTPACKHLP_VERSION
-- };
--
-- /*
-- * Allocate + initialize our private data.
-- */
-- m = new Data;
-- VBoxExtPackInitDesc(&m->Desc);
-- m->Desc.strName = a_pszName;
-- RT_ZERO(m->ObjInfoDesc);
-- m->fUsable = false;
-- m->strWhyUnusable = tr("ExtPack::init failed");
-- m->strExtPackPath = a_pszDir;
-- RT_ZERO(m->ObjInfoExtPack);
-- m->strMainModPath.setNull();
-- RT_ZERO(m->ObjInfoMainMod);
-- m->hMainMod = NIL_RTLDRMOD;
-- m->Hlp = s_HlpTmpl;
-- m->Hlp.pszVBoxVersion = RTBldCfgVersion();
-- m->Hlp.uVBoxInternalRevision = RTBldCfgRevision();
-- m->pThis = this;
-- m->pReg = NULL;
-- m->enmContext = a_enmContext;
-- m->fMadeReadyCall = false;
--
-- /*
-- * Probe the extension pack (this code is shared with refresh()).
-- */
-- probeAndLoad();
--
-- autoInitSpan.setSucceeded();
-- return S_OK;
--}
--
--/**
-- * COM cruft.
-- */
--void ExtPack::FinalRelease()
--{
-- uninit();
--}
--
--/**
-- * Do the actual cleanup.
-- */
--void ExtPack::uninit()
--{
-- /* Enclose the state transition Ready->InUninit->NotReady */
-- AutoUninitSpan autoUninitSpan(this);
-- if (!autoUninitSpan.uninitDone() && m != NULL)
-- {
-- if (m->hMainMod != NIL_RTLDRMOD)
-- {
-- AssertPtr(m->pReg);
-- if (m->pReg->pfnUnload != NULL)
-- m->pReg->pfnUnload(m->pReg);
--
-- RTLdrClose(m->hMainMod);
-- m->hMainMod = NIL_RTLDRMOD;
-- m->pReg = NULL;
-- }
--
-- VBoxExtPackFreeDesc(&m->Desc);
--
-- delete m;
-- m = NULL;
-- }
--}
--
--
--/**
-- * Calls the installed hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pVirtualBox The VirtualBox interface.
-- * @param a_pLock The write lock held by the caller.
-- * @param pErrInfo Where to return error information.
-- */
--bool ExtPack::callInstalledHook(IVirtualBox *a_pVirtualBox, AutoWriteLock *a_pLock, PRTERRINFO pErrInfo)
--{
-- if ( m != NULL
-- && m->hMainMod != NIL_RTLDRMOD)
-- {
-- if (m->pReg->pfnInstalled)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- pErrInfo->rc = m->pReg->pfnInstalled(m->pReg, a_pVirtualBox, pErrInfo);
-- a_pLock->acquire();
-- return true;
-- }
-- }
-- pErrInfo->rc = VINF_SUCCESS;
-- return false;
--}
--
--/**
-- * Calls the uninstall hook and closes the module.
-- *
-- * @returns S_OK or COM error status with error information.
-- * @param a_pVirtualBox The VirtualBox interface.
-- * @param a_fForcedRemoval When set, we'll ignore complaints from the
-- * uninstall hook.
-- * @remarks The caller holds the manager's write lock, not released.
-- */
--HRESULT ExtPack::callUninstallHookAndClose(IVirtualBox *a_pVirtualBox, bool a_fForcedRemoval)
--{
-- HRESULT hrc = S_OK;
--
-- if ( m != NULL
-- && m->hMainMod != NIL_RTLDRMOD)
-- {
-- if (m->pReg->pfnUninstall && !a_fForcedRemoval)
-- {
-- int vrc = m->pReg->pfnUninstall(m->pReg, a_pVirtualBox);
-- if (RT_FAILURE(vrc))
-- {
-- LogRel(("ExtPack pfnUninstall returned %Rrc for %s\n", vrc, m->Desc.strName.c_str()));
-- if (!a_fForcedRemoval)
-- hrc = setError(E_FAIL, tr("pfnUninstall returned %Rrc"), vrc);
-- }
-- }
-- if (SUCCEEDED(hrc))
-- {
-- RTLdrClose(m->hMainMod);
-- m->hMainMod = NIL_RTLDRMOD;
-- m->pReg = NULL;
-- }
-- }
--
-- return hrc;
--}
--
--/**
-- * Calls the pfnVirtualBoxReady hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pVirtualBox The VirtualBox interface.
-- * @param a_pLock The write lock held by the caller.
-- */
--bool ExtPack::callVirtualBoxReadyHook(IVirtualBox *a_pVirtualBox, AutoWriteLock *a_pLock)
--{
-- if ( m != NULL
-- && m->fUsable
-- && !m->fMadeReadyCall)
-- {
-- m->fMadeReadyCall = true;
-- if (m->pReg->pfnVirtualBoxReady)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- m->pReg->pfnVirtualBoxReady(m->pReg, a_pVirtualBox);
-- a_pLock->acquire();
-- return true;
-- }
-- }
-- return false;
--}
--
--/**
-- * Calls the pfnConsoleReady hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pConsole The Console interface.
-- * @param a_pLock The write lock held by the caller.
-- */
--bool ExtPack::callConsoleReadyHook(IConsole *a_pConsole, AutoWriteLock *a_pLock)
--{
-- if ( m != NULL
-- && m->fUsable
-- && !m->fMadeReadyCall)
-- {
-- m->fMadeReadyCall = true;
-- if (m->pReg->pfnConsoleReady)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- m->pReg->pfnConsoleReady(m->pReg, a_pConsole);
-- a_pLock->acquire();
-- return true;
-- }
-- }
-- return false;
--}
--
--/**
-- * Calls the pfnVMCreate hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pVirtualBox The VirtualBox interface.
-- * @param a_pMachine The machine interface of the new VM.
-- * @param a_pLock The write lock held by the caller.
-- */
--bool ExtPack::callVmCreatedHook(IVirtualBox *a_pVirtualBox, IMachine *a_pMachine, AutoWriteLock *a_pLock)
--{
-- if ( m != NULL
-- && m->fUsable)
-- {
-- if (m->pReg->pfnVMCreated)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- m->pReg->pfnVMCreated(m->pReg, a_pVirtualBox, a_pMachine);
-- a_pLock->acquire();
-- return true;
-- }
-- }
-- return false;
--}
--
--/**
-- * Calls the pfnVMConfigureVMM hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pConsole The console interface.
-- * @param a_pVM The VM handle.
-- * @param a_pLock The write lock held by the caller.
-- * @param a_pvrc Where to return the status code of the
-- * callback. This is always set. LogRel is
-- * called on if a failure status is returned.
-- */
--bool ExtPack::callVmConfigureVmmHook(IConsole *a_pConsole, PVM a_pVM, AutoWriteLock *a_pLock, int *a_pvrc)
--{
-- *a_pvrc = VINF_SUCCESS;
-- if ( m != NULL
-- && m->fUsable)
-- {
-- if (m->pReg->pfnVMConfigureVMM)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- int vrc = m->pReg->pfnVMConfigureVMM(m->pReg, a_pConsole, a_pVM);
-- *a_pvrc = vrc;
-- a_pLock->acquire();
-- if (RT_FAILURE(vrc))
-- LogRel(("ExtPack pfnVMConfigureVMM returned %Rrc for %s\n", vrc, m->Desc.strName.c_str()));
-- return true;
-- }
-- }
-- return false;
--}
--
--/**
-- * Calls the pfnVMPowerOn hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pConsole The console interface.
-- * @param a_pVM The VM handle.
-- * @param a_pLock The write lock held by the caller.
-- * @param a_pvrc Where to return the status code of the
-- * callback. This is always set. LogRel is
-- * called on if a failure status is returned.
-- */
--bool ExtPack::callVmPowerOnHook(IConsole *a_pConsole, PVM a_pVM, AutoWriteLock *a_pLock, int *a_pvrc)
--{
-- *a_pvrc = VINF_SUCCESS;
-- if ( m != NULL
-- && m->fUsable)
-- {
-- if (m->pReg->pfnVMPowerOn)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- int vrc = m->pReg->pfnVMPowerOn(m->pReg, a_pConsole, a_pVM);
-- *a_pvrc = vrc;
-- a_pLock->acquire();
-- if (RT_FAILURE(vrc))
-- LogRel(("ExtPack pfnVMPowerOn returned %Rrc for %s\n", vrc, m->Desc.strName.c_str()));
-- return true;
-- }
-- }
-- return false;
--}
--
--/**
-- * Calls the pfnVMPowerOff hook.
-- *
-- * @returns true if we left the lock, false if we didn't.
-- * @param a_pConsole The console interface.
-- * @param a_pVM The VM handle.
-- * @param a_pLock The write lock held by the caller.
-- */
--bool ExtPack::callVmPowerOffHook(IConsole *a_pConsole, PVM a_pVM, AutoWriteLock *a_pLock)
--{
-- if ( m != NULL
-- && m->fUsable)
-- {
-- if (m->pReg->pfnVMPowerOff)
-- {
-- ComPtr<ExtPack> ptrSelfRef = this;
-- a_pLock->release();
-- m->pReg->pfnVMPowerOff(m->pReg, a_pConsole, a_pVM);
-- a_pLock->acquire();
-- return true;
-- }
-- }
-- return false;
--}
--
--/**
-- * Check if the extension pack is usable and has an VRDE module.
-- *
-- * @returns S_OK or COM error status with error information.
-- *
-- * @remarks Caller holds the extension manager lock for reading, no locking
-- * necessary.
-- */
--HRESULT ExtPack::checkVrde(void)
--{
-- HRESULT hrc;
-- if ( m != NULL
-- && m->fUsable)
-- {
-- if (m->Desc.strVrdeModule.isNotEmpty())
-- hrc = S_OK;
-- else
-- hrc = setError(E_FAIL, tr("The extension pack '%s' does not include a VRDE module"), m->Desc.strName.c_str());
-- }
-- else
-- hrc = setError(E_FAIL, tr("%s"), m->strWhyUnusable.c_str());
-- return hrc;
--}
--
--/**
-- * Same as checkVrde(), except that it also resolves the path to the module.
-- *
-- * @returns S_OK or COM error status with error information.
-- * @param a_pstrVrdeLibrary Where to return the path on success.
-- *
-- * @remarks Caller holds the extension manager lock for reading, no locking
-- * necessary.
-- */
--HRESULT ExtPack::getVrdpLibraryName(Utf8Str *a_pstrVrdeLibrary)
--{
-- HRESULT hrc = checkVrde();
-- if (SUCCEEDED(hrc))
-- {
-- if (findModule(m->Desc.strVrdeModule.c_str(), NULL, VBOXEXTPACKMODKIND_R3,
-- a_pstrVrdeLibrary, NULL /*a_pfNative*/, NULL /*a_pObjInfo*/))
-- hrc = S_OK;
-- else
-- hrc = setError(E_FAIL, tr("Failed to locate the VRDE module '%s' in extension pack '%s'"),
-- m->Desc.strVrdeModule.c_str(), m->Desc.strName.c_str());
-- }
-- return hrc;
--}
--
--/**
-- * Check if this extension pack wishes to be the default VRDE provider.
-- *
-- * @returns @c true if it wants to and it is in a usable state, otherwise
-- * @c false.
-- *
-- * @remarks Caller holds the extension manager lock for reading, no locking
-- * necessary.
-- */
--bool ExtPack::wantsToBeDefaultVrde(void) const
--{
-- return m->fUsable
-- && m->Desc.strVrdeModule.isNotEmpty();
--}
--
--/**
-- * Refreshes the extension pack state.
-- *
-- * This is called by the manager so that the on disk changes are picked up.
-- *
-- * @returns S_OK or COM error status with error information.
-- *
-- * @param a_pfCanDelete Optional can-delete-this-object output indicator.
-- *
-- * @remarks Caller holds the extension manager lock for writing.
-- * @remarks Only called in VBoxSVC.
-- */
--HRESULT ExtPack::refresh(bool *a_pfCanDelete)
--{
-- if (a_pfCanDelete)
-- *a_pfCanDelete = false;
--
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS); /* for the COMGETTERs */
--
-- /*
-- * Has the module been deleted?
-- */
-- RTFSOBJINFO ObjInfoExtPack;
-- int vrc = RTPathQueryInfoEx(m->strExtPackPath.c_str(), &ObjInfoExtPack, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
-- if ( RT_FAILURE(vrc)
-- || !RTFS_IS_DIRECTORY(ObjInfoExtPack.Attr.fMode))
-- {
-- if (a_pfCanDelete)
-- *a_pfCanDelete = true;
-- return S_OK;
-- }
--
-- /*
-- * We've got a directory, so try query file system object info for the
-- * files we are interested in as well.
-- */
-- RTFSOBJINFO ObjInfoDesc;
-- char szDescFilePath[RTPATH_MAX];
-- vrc = RTPathJoin(szDescFilePath, sizeof(szDescFilePath), m->strExtPackPath.c_str(), VBOX_EXTPACK_DESCRIPTION_NAME);
-- if (RT_SUCCESS(vrc))
-- vrc = RTPathQueryInfoEx(szDescFilePath, &ObjInfoDesc, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
-- if (RT_FAILURE(vrc))
-- RT_ZERO(ObjInfoDesc);
--
-- RTFSOBJINFO ObjInfoMainMod;
-- if (m->strMainModPath.isNotEmpty())
-- vrc = RTPathQueryInfoEx(m->strMainModPath.c_str(), &ObjInfoMainMod, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
-- if (m->strMainModPath.isEmpty() || RT_FAILURE(vrc))
-- RT_ZERO(ObjInfoMainMod);
--
-- /*
-- * If we have a usable module already, just verify that things haven't
-- * changed since we loaded it.
-- */
-- if (m->fUsable)
-- {
-- if (m->hMainMod == NIL_RTLDRMOD)
-- probeAndLoad();
-- else if ( !objinfoIsEqual(&ObjInfoDesc, &m->ObjInfoDesc)
-- || !objinfoIsEqual(&ObjInfoMainMod, &m->ObjInfoMainMod)
-- || !objinfoIsEqual(&ObjInfoExtPack, &m->ObjInfoExtPack) )
-- {
-- /** @todo not important, so it can wait. */
-- }
-- }
-- /*
-- * Ok, it is currently not usable. If anything has changed since last time
-- * reprobe the extension pack.
-- */
-- else if ( !objinfoIsEqual(&ObjInfoDesc, &m->ObjInfoDesc)
-- || !objinfoIsEqual(&ObjInfoMainMod, &m->ObjInfoMainMod)
-- || !objinfoIsEqual(&ObjInfoExtPack, &m->ObjInfoExtPack) )
-- probeAndLoad();
--
-- return S_OK;
--}
--
--/**
-- * Probes the extension pack, loading the main dll and calling its registration
-- * entry point.
-- *
-- * This updates the state accordingly, the strWhyUnusable and fUnusable members
-- * being the most important ones.
-- */
--void ExtPack::probeAndLoad(void)
--{
-- m->fUsable = false;
-- m->fMadeReadyCall = false;
--
-- /*
-- * Query the file system info for the extension pack directory. This and
-- * all other file system info we save is for the benefit of refresh().
-- */
-- int vrc = RTPathQueryInfoEx(m->strExtPackPath.c_str(), &m->ObjInfoExtPack, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
-- if (RT_FAILURE(vrc))
-- {
-- m->strWhyUnusable.printf(tr("RTPathQueryInfoEx on '%s' failed: %Rrc"), m->strExtPackPath.c_str(), vrc);
-- return;
-- }
-- if (!RTFS_IS_DIRECTORY(m->ObjInfoExtPack.Attr.fMode))
-- {
-- if (RTFS_IS_SYMLINK(m->ObjInfoExtPack.Attr.fMode))
-- m->strWhyUnusable.printf(tr("'%s' is a symbolic link, this is not allowed"), m->strExtPackPath.c_str(), vrc);
-- else if (RTFS_IS_FILE(m->ObjInfoExtPack.Attr.fMode))
-- m->strWhyUnusable.printf(tr("'%s' is a symbolic file, not a directory"), m->strExtPackPath.c_str(), vrc);
-- else
-- m->strWhyUnusable.printf(tr("'%s' is not a directory (fMode=%#x)"), m->strExtPackPath.c_str(), m->ObjInfoExtPack.Attr.fMode);
-- return;
-- }
--
-- RTERRINFOSTATIC ErrInfo;
-- RTErrInfoInitStatic(&ErrInfo);
-- vrc = SUPR3HardenedVerifyDir(m->strExtPackPath.c_str(), true /*fRecursive*/, true /*fCheckFiles*/, &ErrInfo.Core);
-- if (RT_FAILURE(vrc))
-- {
-- m->strWhyUnusable.printf(tr("%s (rc=%Rrc)"), ErrInfo.Core.pszMsg, vrc);
-- return;
-- }
--
-- /*
-- * Read the description file.
-- */
-- RTCString strSavedName(m->Desc.strName);
-- RTCString *pStrLoadErr = VBoxExtPackLoadDesc(m->strExtPackPath.c_str(), &m->Desc, &m->ObjInfoDesc);
-- if (pStrLoadErr != NULL)
-- {
-- m->strWhyUnusable.printf(tr("Failed to load '%s/%s': %s"),
-- m->strExtPackPath.c_str(), VBOX_EXTPACK_DESCRIPTION_NAME, pStrLoadErr->c_str());
-- m->Desc.strName = strSavedName;
-- delete pStrLoadErr;
-- return;
-- }
--
-- /*
-- * Make sure the XML name and directory matches.
-- */
-- if (!m->Desc.strName.equalsIgnoreCase(strSavedName))
-- {
-- m->strWhyUnusable.printf(tr("The description name ('%s') and directory name ('%s') does not match"),
-- m->Desc.strName.c_str(), strSavedName.c_str());
-- m->Desc.strName = strSavedName;
-- return;
-- }
--
-- /*
-- * Load the main DLL and call the predefined entry point.
-- */
-- bool fIsNative;
-- if (!findModule(m->Desc.strMainModule.c_str(), NULL /* default extension */, VBOXEXTPACKMODKIND_R3,
-- &m->strMainModPath, &fIsNative, &m->ObjInfoMainMod))
-- {
-- m->strWhyUnusable.printf(tr("Failed to locate the main module ('%s')"), m->Desc.strMainModule.c_str());
-- return;
-- }
--
-- vrc = SUPR3HardenedVerifyPlugIn(m->strMainModPath.c_str(), &ErrInfo.Core);
-- if (RT_FAILURE(vrc))
-- {
-- m->strWhyUnusable.printf(tr("%s"), ErrInfo.Core.pszMsg);
-- return;
-- }
--
-- if (fIsNative)
-- {
-- vrc = SUPR3HardenedLdrLoadPlugIn(m->strMainModPath.c_str(), &m->hMainMod, &ErrInfo.Core);
-- if (RT_FAILURE(vrc))
-- {
-- m->hMainMod = NIL_RTLDRMOD;
-- m->strWhyUnusable.printf(tr("Failed to load the main module ('%s'): %Rrc - %s"),
-- m->strMainModPath.c_str(), vrc, ErrInfo.Core.pszMsg);
-- return;
-- }
-- }
-- else
-- {
-- m->strWhyUnusable.printf(tr("Only native main modules are currently supported"));
-- return;
-- }
--
-- /*
-- * Resolve the predefined entry point.
-- */
-- PFNVBOXEXTPACKREGISTER pfnRegistration;
-- vrc = RTLdrGetSymbol(m->hMainMod, VBOX_EXTPACK_MAIN_MOD_ENTRY_POINT, (void **)&pfnRegistration);
-- if (RT_SUCCESS(vrc))
-- {
-- RTErrInfoClear(&ErrInfo.Core);
-- vrc = pfnRegistration(&m->Hlp, &m->pReg, &ErrInfo.Core);
-- if ( RT_SUCCESS(vrc)
-- && !RTErrInfoIsSet(&ErrInfo.Core)
-- && VALID_PTR(m->pReg))
-- {
-- if ( VBOXEXTPACK_IS_MAJOR_VER_EQUAL(m->pReg->u32Version, VBOXEXTPACKREG_VERSION)
-- && m->pReg->u32EndMarker == m->pReg->u32Version)
-- {
-- if ( (!m->pReg->pfnInstalled || RT_VALID_PTR(m->pReg->pfnInstalled))
-- && (!m->pReg->pfnUninstall || RT_VALID_PTR(m->pReg->pfnUninstall))
-- && (!m->pReg->pfnVirtualBoxReady || RT_VALID_PTR(m->pReg->pfnVirtualBoxReady))
-- && (!m->pReg->pfnConsoleReady || RT_VALID_PTR(m->pReg->pfnConsoleReady))
-- && (!m->pReg->pfnUnload || RT_VALID_PTR(m->pReg->pfnUnload))
-- && (!m->pReg->pfnVMCreated || RT_VALID_PTR(m->pReg->pfnVMCreated))
-- && (!m->pReg->pfnVMConfigureVMM || RT_VALID_PTR(m->pReg->pfnVMConfigureVMM))
-- && (!m->pReg->pfnVMPowerOn || RT_VALID_PTR(m->pReg->pfnVMPowerOn))
-- && (!m->pReg->pfnVMPowerOff || RT_VALID_PTR(m->pReg->pfnVMPowerOff))
-- && (!m->pReg->pfnQueryObject || RT_VALID_PTR(m->pReg->pfnQueryObject))
-- )
-- {
-- /*
-- * We're good!
-- */
-- m->fUsable = true;
-- m->strWhyUnusable.setNull();
-- return;
-- }
--
-- m->strWhyUnusable = tr("The registration structure contains on or more invalid function pointers");
-- }
-- else
-- m->strWhyUnusable.printf(tr("Unsupported registration structure version %u.%u"),
-- RT_HIWORD(m->pReg->u32Version), RT_LOWORD(m->pReg->u32Version));
-- }
-- else
-- m->strWhyUnusable.printf(tr("%s returned %Rrc, pReg=%p ErrInfo='%s'"),
-- VBOX_EXTPACK_MAIN_MOD_ENTRY_POINT, vrc, m->pReg, ErrInfo.Core.pszMsg);
-- m->pReg = NULL;
-- }
-- else
-- m->strWhyUnusable.printf(tr("Failed to resolve exported symbol '%s' in the main module: %Rrc"),
-- VBOX_EXTPACK_MAIN_MOD_ENTRY_POINT, vrc);
--
-- RTLdrClose(m->hMainMod);
-- m->hMainMod = NIL_RTLDRMOD;
--}
--
--/**
-- * Finds a module.
-- *
-- * @returns true if found, false if not.
-- * @param a_pszName The module base name (no extension).
-- * @param a_pszExt The extension. If NULL we use default
-- * extensions.
-- * @param a_enmKind The kind of module to locate.
-- * @param a_pStrFound Where to return the path to the module we've
-- * found.
-- * @param a_pfNative Where to return whether this is a native module
-- * or an agnostic one. Optional.
-- * @param a_pObjInfo Where to return the file system object info for
-- * the module. Optional.
-- */
--bool ExtPack::findModule(const char *a_pszName, const char *a_pszExt, VBOXEXTPACKMODKIND a_enmKind,
-- Utf8Str *a_pStrFound, bool *a_pfNative, PRTFSOBJINFO a_pObjInfo) const
--{
-- /*
-- * Try the native path first.
-- */
-- char szPath[RTPATH_MAX];
-- int vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), RTBldCfgTargetDotArch());
-- AssertLogRelRCReturn(vrc, false);
-- vrc = RTPathAppend(szPath, sizeof(szPath), a_pszName);
-- AssertLogRelRCReturn(vrc, false);
-- if (!a_pszExt)
-- {
-- const char *pszDefExt;
-- switch (a_enmKind)
-- {
-- case VBOXEXTPACKMODKIND_RC: pszDefExt = ".rc"; break;
-- case VBOXEXTPACKMODKIND_R0: pszDefExt = ".r0"; break;
-- case VBOXEXTPACKMODKIND_R3: pszDefExt = RTLdrGetSuff(); break;
-- default:
-- AssertFailedReturn(false);
-- }
-- vrc = RTStrCat(szPath, sizeof(szPath), pszDefExt);
-- AssertLogRelRCReturn(vrc, false);
-- }
--
-- RTFSOBJINFO ObjInfo;
-- if (!a_pObjInfo)
-- a_pObjInfo = &ObjInfo;
-- vrc = RTPathQueryInfo(szPath, a_pObjInfo, RTFSOBJATTRADD_UNIX);
-- if (RT_SUCCESS(vrc) && RTFS_IS_FILE(a_pObjInfo->Attr.fMode))
-- {
-- if (a_pfNative)
-- *a_pfNative = true;
-- *a_pStrFound = szPath;
-- return true;
-- }
--
-- /*
-- * Try the platform agnostic modules.
-- */
-- /* gcc.x86/module.rel */
-- char szSubDir[32];
-- RTStrPrintf(szSubDir, sizeof(szSubDir), "%s.%s", RTBldCfgCompiler(), RTBldCfgTargetArch());
-- vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), szSubDir);
-- AssertLogRelRCReturn(vrc, false);
-- vrc = RTPathAppend(szPath, sizeof(szPath), a_pszName);
-- AssertLogRelRCReturn(vrc, false);
-- if (!a_pszExt)
-- {
-- vrc = RTStrCat(szPath, sizeof(szPath), ".rel");
-- AssertLogRelRCReturn(vrc, false);
-- }
-- vrc = RTPathQueryInfo(szPath, a_pObjInfo, RTFSOBJATTRADD_UNIX);
-- if (RT_SUCCESS(vrc) && RTFS_IS_FILE(a_pObjInfo->Attr.fMode))
-- {
-- if (a_pfNative)
-- *a_pfNative = false;
-- *a_pStrFound = szPath;
-- return true;
-- }
--
-- /* x86/module.rel */
-- vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), RTBldCfgTargetArch());
-- AssertLogRelRCReturn(vrc, false);
-- vrc = RTPathAppend(szPath, sizeof(szPath), a_pszName);
-- AssertLogRelRCReturn(vrc, false);
-- if (!a_pszExt)
-- {
-- vrc = RTStrCat(szPath, sizeof(szPath), ".rel");
-- AssertLogRelRCReturn(vrc, false);
-- }
-- vrc = RTPathQueryInfo(szPath, a_pObjInfo, RTFSOBJATTRADD_UNIX);
-- if (RT_SUCCESS(vrc) && RTFS_IS_FILE(a_pObjInfo->Attr.fMode))
-- {
-- if (a_pfNative)
-- *a_pfNative = false;
-- *a_pStrFound = szPath;
-- return true;
-- }
--
-- return false;
--}
--
--/**
-- * Compares two file system object info structures.
-- *
-- * @returns true if equal, false if not.
-- * @param pObjInfo1 The first.
-- * @param pObjInfo2 The second.
-- * @todo IPRT should do this, really.
-- */
--/* static */ bool ExtPack::objinfoIsEqual(PCRTFSOBJINFO pObjInfo1, PCRTFSOBJINFO pObjInfo2)
--{
-- if (!RTTimeSpecIsEqual(&pObjInfo1->ModificationTime, &pObjInfo2->ModificationTime))
-- return false;
-- if (!RTTimeSpecIsEqual(&pObjInfo1->ChangeTime, &pObjInfo2->ChangeTime))
-- return false;
-- if (!RTTimeSpecIsEqual(&pObjInfo1->BirthTime, &pObjInfo2->BirthTime))
-- return false;
-- if (pObjInfo1->cbObject != pObjInfo2->cbObject)
-- return false;
-- if (pObjInfo1->Attr.fMode != pObjInfo2->Attr.fMode)
-- return false;
-- if (pObjInfo1->Attr.enmAdditional == pObjInfo2->Attr.enmAdditional)
-- {
-- switch (pObjInfo1->Attr.enmAdditional)
-- {
-- case RTFSOBJATTRADD_UNIX:
-- if (pObjInfo1->Attr.u.Unix.uid != pObjInfo2->Attr.u.Unix.uid)
-- return false;
-- if (pObjInfo1->Attr.u.Unix.gid != pObjInfo2->Attr.u.Unix.gid)
-- return false;
-- if (pObjInfo1->Attr.u.Unix.INodeIdDevice != pObjInfo2->Attr.u.Unix.INodeIdDevice)
-- return false;
-- if (pObjInfo1->Attr.u.Unix.INodeId != pObjInfo2->Attr.u.Unix.INodeId)
-- return false;
-- if (pObjInfo1->Attr.u.Unix.GenerationId != pObjInfo2->Attr.u.Unix.GenerationId)
-- return false;
-- break;
-- default:
-- break;
-- }
-- }
-- return true;
--}
--
--
--/**
-- * @interface_method_impl{VBOXEXTPACKHLP,pfnFindModule}
-- */
--/*static*/ DECLCALLBACK(int)
--ExtPack::hlpFindModule(PCVBOXEXTPACKHLP pHlp, const char *pszName, const char *pszExt, VBOXEXTPACKMODKIND enmKind,
-- char *pszFound, size_t cbFound, bool *pfNative)
--{
-- /*
-- * Validate the input and get our bearings.
-- */
-- AssertPtrReturn(pszName, VERR_INVALID_POINTER);
-- AssertPtrNullReturn(pszExt, VERR_INVALID_POINTER);
-- AssertPtrReturn(pszFound, VERR_INVALID_POINTER);
-- AssertPtrNullReturn(pfNative, VERR_INVALID_POINTER);
-- AssertReturn(enmKind > VBOXEXTPACKMODKIND_INVALID && enmKind < VBOXEXTPACKMODKIND_END, VERR_INVALID_PARAMETER);
--
-- AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
-- AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
-- ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
-- AssertPtrReturn(m, VERR_INVALID_POINTER);
-- ExtPack *pThis = m->pThis;
-- AssertPtrReturn(pThis, VERR_INVALID_POINTER);
--
-- /*
-- * This is just a wrapper around findModule.
-- */
-- Utf8Str strFound;
-- if (pThis->findModule(pszName, pszExt, enmKind, &strFound, pfNative, NULL))
-- return RTStrCopy(pszFound, cbFound, strFound.c_str());
-- return VERR_FILE_NOT_FOUND;
--}
--
--/*static*/ DECLCALLBACK(int)
--ExtPack::hlpGetFilePath(PCVBOXEXTPACKHLP pHlp, const char *pszFilename, char *pszPath, size_t cbPath)
--{
-- /*
-- * Validate the input and get our bearings.
-- */
-- AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
-- AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
-- AssertReturn(cbPath > 0, VERR_BUFFER_OVERFLOW);
--
-- AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
-- AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
-- ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
-- AssertPtrReturn(m, VERR_INVALID_POINTER);
-- ExtPack *pThis = m->pThis;
-- AssertPtrReturn(pThis, VERR_INVALID_POINTER);
--
-- /*
-- * This is a simple RTPathJoin, no checking if things exists or anything.
-- */
-- int vrc = RTPathJoin(pszPath, cbPath, pThis->m->strExtPackPath.c_str(), pszFilename);
-- if (RT_FAILURE(vrc))
-- RT_BZERO(pszPath, cbPath);
-- return vrc;
--}
--
--/*static*/ DECLCALLBACK(VBOXEXTPACKCTX)
--ExtPack::hlpGetContext(PCVBOXEXTPACKHLP pHlp)
--{
-- /*
-- * Validate the input and get our bearings.
-- */
-- AssertPtrReturn(pHlp, VBOXEXTPACKCTX_INVALID);
-- AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VBOXEXTPACKCTX_INVALID);
-- ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
-- AssertPtrReturn(m, VBOXEXTPACKCTX_INVALID);
-- ExtPack *pThis = m->pThis;
-- AssertPtrReturn(pThis, VBOXEXTPACKCTX_INVALID);
--
-- return pThis->m->enmContext;
--}
--
--/*static*/ DECLCALLBACK(int)
--ExtPack::hlpReservedN(PCVBOXEXTPACKHLP pHlp)
--{
-- /*
-- * Validate the input and get our bearings.
-- */
-- AssertPtrReturn(pHlp, VERR_INVALID_POINTER);
-- AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, VERR_INVALID_POINTER);
-- ExtPack::Data *m = RT_FROM_CPP_MEMBER(pHlp, Data, Hlp);
-- AssertPtrReturn(m, VERR_INVALID_POINTER);
-- ExtPack *pThis = m->pThis;
-- AssertPtrReturn(pThis, VERR_INVALID_POINTER);
--
-- return VERR_NOT_IMPLEMENTED;
--}
--
--
--
--
--
--STDMETHODIMP ExtPack::COMGETTER(Name)(BSTR *a_pbstrName)
--{
-- CheckComArgOutPointerValid(a_pbstrName);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strName);
-- str.cloneTo(a_pbstrName);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(Description)(BSTR *a_pbstrDescription)
--{
-- CheckComArgOutPointerValid(a_pbstrDescription);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strDescription);
-- str.cloneTo(a_pbstrDescription);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(Version)(BSTR *a_pbstrVersion)
--{
-- CheckComArgOutPointerValid(a_pbstrVersion);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strVersion);
-- str.cloneTo(a_pbstrVersion);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(Revision)(ULONG *a_puRevision)
--{
-- CheckComArgOutPointerValid(a_puRevision);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- *a_puRevision = m->Desc.uRevision;
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(Edition)(BSTR *a_pbstrEdition)
--{
-- CheckComArgOutPointerValid(a_pbstrEdition);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strEdition);
-- str.cloneTo(a_pbstrEdition);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(VRDEModule)(BSTR *a_pbstrVrdeModule)
--{
-- CheckComArgOutPointerValid(a_pbstrVrdeModule);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr str(m->Desc.strVrdeModule);
-- str.cloneTo(a_pbstrVrdeModule);
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(PlugIns)(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns))
--{
-- /** @todo implement plug-ins. */
--#ifdef VBOX_WITH_XPCOM
-- NOREF(a_paPlugIns);
-- NOREF(a_paPlugInsSize);
--#endif
-- ReturnComNotImplemented();
--}
--
--STDMETHODIMP ExtPack::COMGETTER(Usable)(BOOL *a_pfUsable)
--{
-- CheckComArgOutPointerValid(a_pfUsable);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- *a_pfUsable = m->fUsable;
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(WhyUnusable)(BSTR *a_pbstrWhy)
--{
-- CheckComArgOutPointerValid(a_pbstrWhy);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- m->strWhyUnusable.cloneTo(a_pbstrWhy);
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(ShowLicense)(BOOL *a_pfShowIt)
--{
-- CheckComArgOutPointerValid(a_pfShowIt);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- *a_pfShowIt = m->Desc.fShowLicense;
-- return hrc;
--}
--
--STDMETHODIMP ExtPack::COMGETTER(License)(BSTR *a_pbstrHtmlLicense)
--{
-- Bstr bstrHtml("html");
-- return QueryLicense(Bstr::Empty.raw(), Bstr::Empty.raw(), bstrHtml.raw(), a_pbstrHtmlLicense);
--}
--
--STDMETHODIMP ExtPack::QueryLicense(IN_BSTR a_bstrPreferredLocale, IN_BSTR a_bstrPreferredLanguage, IN_BSTR a_bstrFormat,
-- BSTR *a_pbstrLicense)
--{
-- /*
-- * Validate input.
-- */
-- CheckComArgOutPointerValid(a_pbstrLicense);
-- CheckComArgNotNull(a_bstrPreferredLocale);
-- CheckComArgNotNull(a_bstrPreferredLanguage);
-- CheckComArgNotNull(a_bstrFormat);
--
-- Utf8Str strPreferredLocale(a_bstrPreferredLocale);
-- if (strPreferredLocale.length() != 2 && strPreferredLocale.length() != 0)
-- return setError(E_FAIL, tr("The preferred locale is a two character string or empty."));
--
-- Utf8Str strPreferredLanguage(a_bstrPreferredLanguage);
-- if (strPreferredLanguage.length() != 2 && strPreferredLanguage.length() != 0)
-- return setError(E_FAIL, tr("The preferred lanuage is a two character string or empty."));
--
-- Utf8Str strFormat(a_bstrFormat);
-- if ( !strFormat.equals("html")
-- && !strFormat.equals("rtf")
-- && !strFormat.equals("txt"))
-- return setError(E_FAIL, tr("The license format can only have the values 'html', 'rtf' and 'txt'."));
--
-- /*
-- * Combine the options to form a file name before locking down anything.
-- */
-- char szName[sizeof(VBOX_EXTPACK_LICENSE_NAME_PREFIX "-de_DE.html") + 2];
-- if (strPreferredLocale.isNotEmpty() && strPreferredLanguage.isNotEmpty())
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX "-%s_%s.%s",
-- strPreferredLocale.c_str(), strPreferredLanguage.c_str(), strFormat.c_str());
-- else if (strPreferredLocale.isNotEmpty())
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX "-%s.%s", strPreferredLocale.c_str(), strFormat.c_str());
-- else if (strPreferredLanguage.isNotEmpty())
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX "-_%s.%s", strPreferredLocale.c_str(), strFormat.c_str());
-- else
-- RTStrPrintf(szName, sizeof(szName), VBOX_EXTPACK_LICENSE_NAME_PREFIX ".%s", strFormat.c_str());
--
-- /*
-- * Effectuate the query.
-- */
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS); /* paranoia */
--
-- if (!m->fUsable)
-- hrc = setError(E_FAIL, tr("%s"), m->strWhyUnusable.c_str());
-- else
-- {
-- char szPath[RTPATH_MAX];
-- int vrc = RTPathJoin(szPath, sizeof(szPath), m->strExtPackPath.c_str(), szName);
-- if (RT_SUCCESS(vrc))
-- {
-- void *pvFile;
-- size_t cbFile;
-- vrc = RTFileReadAllEx(szPath, 0, RTFOFF_MAX, RTFILE_RDALL_O_DENY_READ, &pvFile, &cbFile);
-- if (RT_SUCCESS(vrc))
-- {
-- Bstr bstrLicense((const char *)pvFile, cbFile);
-- if (bstrLicense.isNotEmpty())
-- {
-- bstrLicense.detachTo(a_pbstrLicense);
-- hrc = S_OK;
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("The license file '%s' is empty or contains invalid UTF-8 encoding"),
-- szPath);
-- RTFileReadAllFree(pvFile, cbFile);
-- }
-- else if (vrc == VERR_FILE_NOT_FOUND || vrc == VERR_PATH_NOT_FOUND)
-- hrc = setError(VBOX_E_OBJECT_NOT_FOUND, tr("The license file '%s' was not found in extension pack '%s'"),
-- szName, m->Desc.strName.c_str());
-- else
-- hrc = setError(VBOX_E_FILE_ERROR, tr("Failed to open the license file '%s': %Rrc"), szPath, vrc);
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("RTPathJoin failed: %Rrc"), vrc);
-- }
-- }
-- return hrc;
--}
--
--
--STDMETHODIMP ExtPack::QueryObject(IN_BSTR a_bstrObjectId, IUnknown **a_ppUnknown)
--{
-- com::Guid ObjectId;
-- CheckComArgGuid(a_bstrObjectId, ObjectId);
-- CheckComArgOutPointerValid(a_ppUnknown);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- if ( m->pReg
-- && m->pReg->pfnQueryObject)
-- {
-- void *pvUnknown = m->pReg->pfnQueryObject(m->pReg, ObjectId.raw());
-- if (pvUnknown)
-- *a_ppUnknown = (IUnknown *)pvUnknown;
-- else
-- hrc = E_NOINTERFACE;
-- }
-- else
-- hrc = E_NOINTERFACE;
-- }
-- return hrc;
--}
--
--
--
--
--DEFINE_EMPTY_CTOR_DTOR(ExtPackManager)
--
--/**
-- * Called by ComObjPtr::createObject when creating the object.
-- *
-- * Just initialize the basic object state, do the rest in init().
-- *
-- * @returns S_OK.
-- */
--HRESULT ExtPackManager::FinalConstruct()
--{
-- m = NULL;
-- return S_OK;
--}
--
--/**
-- * Initializes the extension pack manager.
-- *
-- * @returns COM status code.
-- * @param a_pVirtualBox Pointer to the VirtualBox object.
-- * @param a_enmContext The context we're in.
-- */
--HRESULT ExtPackManager::initExtPackManager(VirtualBox *a_pVirtualBox, VBOXEXTPACKCTX a_enmContext)
--{
-- AutoInitSpan autoInitSpan(this);
-- AssertReturn(autoInitSpan.isOk(), E_FAIL);
--
-- /*
-- * Figure some stuff out before creating the instance data.
-- */
-- char szBaseDir[RTPATH_MAX];
-- int rc = RTPathAppPrivateArchTop(szBaseDir, sizeof(szBaseDir));
-- AssertLogRelRCReturn(rc, E_FAIL);
-- rc = RTPathAppend(szBaseDir, sizeof(szBaseDir), VBOX_EXTPACK_INSTALL_DIR);
-- AssertLogRelRCReturn(rc, E_FAIL);
--
-- char szCertificatDir[RTPATH_MAX];
-- rc = RTPathAppPrivateNoArch(szCertificatDir, sizeof(szCertificatDir));
-- AssertLogRelRCReturn(rc, E_FAIL);
-- rc = RTPathAppend(szCertificatDir, sizeof(szCertificatDir), VBOX_EXTPACK_CERT_DIR);
-- AssertLogRelRCReturn(rc, E_FAIL);
--
-- /*
-- * Allocate and initialize the instance data.
-- */
-- m = new Data;
-- m->strBaseDir = szBaseDir;
-- m->strCertificatDirPath = szCertificatDir;
-- m->pVirtualBox = a_pVirtualBox;
-- m->enmContext = a_enmContext;
--
-- /*
-- * Slurp in VBoxVMM which is used by VBoxPuelMain.
-- */
--#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_DARWIN)
-- if (a_enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON)
-- {
-- int vrc = SUPR3HardenedLdrLoadAppPriv("VBoxVMM", &m->hVBoxVMM, RTLDRLOAD_FLAGS_GLOBAL, NULL);
-- if (RT_FAILURE(vrc))
-- m->hVBoxVMM = NIL_RTLDRMOD;
-- /* cleanup in ::uninit()? */
-- }
--#endif
--
-- /*
-- * Go looking for extensions. The RTDirOpen may fail if nothing has been
-- * installed yet, or if root is paranoid and has revoked our access to them.
-- *
-- * We ASSUME that there are no files, directories or stuff in the directory
-- * that exceed the max name length in RTDIRENTRYEX.
-- */
-- HRESULT hrc = S_OK;
-- PRTDIR pDir;
-- int vrc = RTDirOpen(&pDir, szBaseDir);
-- if (RT_SUCCESS(vrc))
-- {
-- for (;;)
-- {
-- RTDIRENTRYEX Entry;
-- vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
-- if (RT_FAILURE(vrc))
-- {
-- AssertLogRelMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
-- break;
-- }
-- if ( RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)
-- && strcmp(Entry.szName, ".") != 0
-- && strcmp(Entry.szName, "..") != 0
-- && VBoxExtPackIsValidMangledName(Entry.szName) )
-- {
-- /*
-- * All directories are extensions, the shall be nothing but
-- * extensions in this subdirectory.
-- */
-- char szExtPackDir[RTPATH_MAX];
-- vrc = RTPathJoin(szExtPackDir, sizeof(szExtPackDir), m->strBaseDir.c_str(), Entry.szName);
-- AssertLogRelRC(vrc);
-- if (RT_SUCCESS(vrc))
-- {
-- RTCString *pstrName = VBoxExtPackUnmangleName(Entry.szName, RTSTR_MAX);
-- AssertLogRel(pstrName);
-- if (pstrName)
-- {
-- ComObjPtr<ExtPack> NewExtPack;
-- HRESULT hrc2 = NewExtPack.createObject();
-- if (SUCCEEDED(hrc2))
-- hrc2 = NewExtPack->initWithDir(a_enmContext, pstrName->c_str(), szExtPackDir);
-- delete pstrName;
-- if (SUCCEEDED(hrc2))
-- m->llInstalledExtPacks.push_back(NewExtPack);
-- else if (SUCCEEDED(rc))
-- hrc = hrc2;
-- }
-- else
-- hrc = E_UNEXPECTED;
-- }
-- else
-- hrc = E_UNEXPECTED;
-- }
-- }
-- RTDirClose(pDir);
-- }
-- /* else: ignore, the directory probably does not exist or something. */
--
-- if (SUCCEEDED(hrc))
-- autoInitSpan.setSucceeded();
-- return hrc;
--}
--
--/**
-- * COM cruft.
-- */
--void ExtPackManager::FinalRelease()
--{
-- uninit();
--}
--
--/**
-- * Do the actual cleanup.
-- */
--void ExtPackManager::uninit()
--{
-- /* Enclose the state transition Ready->InUninit->NotReady */
-- AutoUninitSpan autoUninitSpan(this);
-- if (!autoUninitSpan.uninitDone() && m != NULL)
-- {
-- delete m;
-- m = NULL;
-- }
--}
--
--
--STDMETHODIMP ExtPackManager::COMGETTER(InstalledExtPacks)(ComSafeArrayOut(IExtPack *, a_paExtPacks))
--{
-- CheckComArgOutSafeArrayPointerValid(a_paExtPacks);
-- Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- SafeIfaceArray<IExtPack> SaExtPacks(m->llInstalledExtPacks);
-- SaExtPacks.detachTo(ComSafeArrayOutArg(a_paExtPacks));
-- }
--
-- return hrc;
--}
--
--STDMETHODIMP ExtPackManager::Find(IN_BSTR a_bstrName, IExtPack **a_pExtPack)
--{
-- CheckComArgNotNull(a_bstrName);
-- CheckComArgOutPointerValid(a_pExtPack);
-- Utf8Str strName(a_bstrName);
-- Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- ComPtr<ExtPack> ptrExtPack = findExtPack(strName.c_str());
-- if (!ptrExtPack.isNull())
-- ptrExtPack.queryInterfaceTo(a_pExtPack);
-- else
-- hrc = VBOX_E_OBJECT_NOT_FOUND;
-- }
--
-- return hrc;
--}
--
--STDMETHODIMP ExtPackManager::OpenExtPackFile(IN_BSTR a_bstrTarballAndDigest, IExtPackFile **a_ppExtPackFile)
--{
-- CheckComArgNotNull(a_bstrTarballAndDigest);
-- CheckComArgOutPointerValid(a_ppExtPackFile);
-- AssertReturn(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON, E_UNEXPECTED);
--
-- /* The API can optionally take a ::SHA-256=<hex-digest> attribute at the
-- end of the file name. This is just a temporary measure for
-- backporting, in 4.2 we'll add another parameter to the method. */
-- Utf8Str strTarball;
-- Utf8Str strDigest;
-- Utf8Str strTarballAndDigest(a_bstrTarballAndDigest);
-- size_t offSha256 = strTarballAndDigest.find("::SHA-256=");
-- if (offSha256 == Utf8Str::npos)
-- strTarball = strTarballAndDigest;
-- else
-- {
-- strTarball = strTarballAndDigest.substr(0, offSha256);
-- strDigest = strTarballAndDigest.substr(offSha256 + sizeof("::SHA-256=") - 1);
-- }
--
-- ComObjPtr<ExtPackFile> NewExtPackFile;
-- HRESULT hrc = NewExtPackFile.createObject();
-- if (SUCCEEDED(hrc))
-- hrc = NewExtPackFile->initWithFile(strTarball.c_str(), strDigest.c_str(), this, m->pVirtualBox);
-- if (SUCCEEDED(hrc))
-- NewExtPackFile.queryInterfaceTo(a_ppExtPackFile);
--
-- return hrc;
--}
--
--STDMETHODIMP ExtPackManager::Uninstall(IN_BSTR a_bstrName, BOOL a_fForcedRemoval, IN_BSTR a_bstrDisplayInfo,
-- IProgress **a_ppProgress)
--{
-- CheckComArgNotNull(a_bstrName);
-- if (a_ppProgress)
-- *a_ppProgress = NULL;
-- Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- PEXTPACKUNINSTALLJOB pJob = NULL;
-- try
-- {
-- pJob = new EXTPACKUNINSTALLJOB;
-- pJob->ptrExtPackMgr = this;
-- pJob->strName = a_bstrName;
-- pJob->fForcedRemoval = a_fForcedRemoval != FALSE;
-- pJob->strDisplayInfo = a_bstrDisplayInfo;
-- hrc = pJob->ptrProgress.createObject();
-- if (SUCCEEDED(hrc))
-- {
-- Bstr bstrDescription = tr("Uninstalling extension pack");
-- hrc = pJob->ptrProgress->init(
--#ifndef VBOX_COM_INPROC
-- m->pVirtualBox,
--#endif
-- static_cast<IExtPackManager *>(this),
-- bstrDescription.raw(),
-- FALSE /*aCancelable*/,
-- NULL /*aId*/);
-- }
-- if (SUCCEEDED(hrc))
-- {
-- ComPtr<Progress> ptrProgress = pJob->ptrProgress;
-- int vrc = RTThreadCreate(NULL /*phThread*/, ExtPackManager::doUninstallThreadProc, pJob, 0,
-- RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ExtPackUninst");
-- if (RT_SUCCESS(vrc))
-- {
-- pJob = NULL; /* the thread deletes it */
-- ptrProgress.queryInterfaceTo(a_ppProgress);
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("RTThreadCreate failed with %Rrc"), vrc);
-- }
-- }
-- catch (std::bad_alloc)
-- {
-- hrc = E_OUTOFMEMORY;
-- }
-- if (pJob)
-- delete pJob;
-- }
--
-- return hrc;
--}
--
--STDMETHODIMP ExtPackManager::Cleanup(void)
--{
-- Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- /*
-- * Run the set-uid-to-root binary that performs the cleanup.
-- *
-- * Take the write lock to prevent conflicts with other calls to this
-- * VBoxSVC instance.
-- */
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- hrc = runSetUidToRootHelper(NULL,
-- "cleanup",
-- "--base-dir", m->strBaseDir.c_str(),
-- (const char *)NULL);
-- }
--
-- return hrc;
--}
--
--STDMETHODIMP ExtPackManager::QueryAllPlugInsForFrontend(IN_BSTR a_bstrFrontend, ComSafeArrayOut(BSTR, a_pabstrPlugInModules))
--{
-- CheckComArgNotNull(a_bstrFrontend);
-- Utf8Str strName(a_bstrFrontend);
-- CheckComArgOutSafeArrayPointerValid(a_pabstrPlugInModules);
-- Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- com::SafeArray<BSTR> saPaths((size_t)0);
-- /** @todo implement plug-ins */
-- saPaths.detachTo(ComSafeArrayOutArg(a_pabstrPlugInModules));
-- }
-- return hrc;
--}
--
--STDMETHODIMP ExtPackManager::IsExtPackUsable(IN_BSTR a_bstrExtPack, BOOL *aUsable)
--{
-- CheckComArgNotNull(a_bstrExtPack);
-- Utf8Str strExtPack(a_bstrExtPack);
-- *aUsable = isExtPackUsable(strExtPack.c_str());
-- return S_OK;
--}
--
--/**
-- * Finds the success indicator string in the stderr output ofr hte helper app.
-- *
-- * @returns Pointer to the indicator.
-- * @param psz The stderr output string. Can be NULL.
-- * @param cch The size of the string.
-- */
--static char *findSuccessIndicator(char *psz, size_t cch)
--{
-- static const char s_szSuccessInd[] = "rcExit=RTEXITCODE_SUCCESS";
-- Assert(!cch || strlen(psz) == cch);
-- if (cch < sizeof(s_szSuccessInd) - 1)
-- return NULL;
-- char *pszInd = &psz[cch - sizeof(s_szSuccessInd) + 1];
-- if (strcmp(s_szSuccessInd, pszInd))
-- return NULL;
-- return pszInd;
--}
--
--/**
-- * Runs the helper application that does the privileged operations.
-- *
-- * @returns S_OK or a failure status with error information set.
-- * @param a_pstrDisplayInfo Platform specific display info hacks.
-- * @param a_pszCommand The command to execute.
-- * @param ... The argument strings that goes along with the
-- * command. Maximum is about 16. Terminated by a
-- * NULL.
-- */
--HRESULT ExtPackManager::runSetUidToRootHelper(Utf8Str const *a_pstrDisplayInfo, const char *a_pszCommand, ...)
--{
-- /*
-- * Calculate the path to the helper application.
-- */
-- char szExecName[RTPATH_MAX];
-- int vrc = RTPathAppPrivateArch(szExecName, sizeof(szExecName));
-- AssertLogRelRCReturn(vrc, E_UNEXPECTED);
--
-- vrc = RTPathAppend(szExecName, sizeof(szExecName), VBOX_EXTPACK_HELPER_NAME);
-- AssertLogRelRCReturn(vrc, E_UNEXPECTED);
--
-- /*
-- * Convert the variable argument list to a RTProcCreate argument vector.
-- */
-- const char *apszArgs[20];
-- unsigned cArgs = 0;
--
-- LogRel(("ExtPack: Executing '%s'", szExecName));
-- apszArgs[cArgs++] = &szExecName[0];
--
-- if ( a_pstrDisplayInfo
-- && a_pstrDisplayInfo->isNotEmpty())
-- {
-- LogRel((" '--display-info-hack' '%s'", a_pstrDisplayInfo->c_str()));
-- apszArgs[cArgs++] = "--display-info-hack";
-- apszArgs[cArgs++] = a_pstrDisplayInfo->c_str();
-- }
--
-- LogRel(("'%s'", a_pszCommand));
-- apszArgs[cArgs++] = a_pszCommand;
--
-- va_list va;
-- va_start(va, a_pszCommand);
-- const char *pszLastArg;
-- for (;;)
-- {
-- AssertReturn(cArgs < RT_ELEMENTS(apszArgs) - 1, E_UNEXPECTED);
-- pszLastArg = va_arg(va, const char *);
-- if (!pszLastArg)
-- break;
-- LogRel((" '%s'", pszLastArg));
-- apszArgs[cArgs++] = pszLastArg;
-- };
-- va_end(va);
--
-- LogRel(("\n"));
-- apszArgs[cArgs] = NULL;
--
-- /*
-- * Create a PIPE which we attach to stderr so that we can read the error
-- * message on failure and report it back to the caller.
-- */
-- RTPIPE hPipeR;
-- RTHANDLE hStdErrPipe;
-- hStdErrPipe.enmType = RTHANDLETYPE_PIPE;
-- vrc = RTPipeCreate(&hPipeR, &hStdErrPipe.u.hPipe, RTPIPE_C_INHERIT_WRITE);
-- AssertLogRelRCReturn(vrc, E_UNEXPECTED);
--
-- /*
-- * Spawn the process.
-- */
-- HRESULT hrc;
-- RTPROCESS hProcess;
-- vrc = RTProcCreateEx(szExecName,
-- apszArgs,
-- RTENV_DEFAULT,
-- 0 /*fFlags*/,
-- NULL /*phStdIn*/,
-- NULL /*phStdOut*/,
-- &hStdErrPipe,
-- NULL /*pszAsUser*/,
-- NULL /*pszPassword*/,
-- &hProcess);
-- if (RT_SUCCESS(vrc))
-- {
-- vrc = RTPipeClose(hStdErrPipe.u.hPipe);
-- hStdErrPipe.u.hPipe = NIL_RTPIPE;
--
-- /*
-- * Read the pipe output until the process completes.
-- */
-- RTPROCSTATUS ProcStatus = { -42, RTPROCEXITREASON_ABEND };
-- size_t cbStdErrBuf = 0;
-- size_t offStdErrBuf = 0;
-- char *pszStdErrBuf = NULL;
-- do
-- {
-- /*
-- * Service the pipe. Block waiting for output or the pipe breaking
-- * when the process terminates.
-- */
-- if (hPipeR != NIL_RTPIPE)
-- {
-- char achBuf[1024];
-- size_t cbRead;
-- vrc = RTPipeReadBlocking(hPipeR, achBuf, sizeof(achBuf), &cbRead);
-- if (RT_SUCCESS(vrc))
-- {
-- /* grow the buffer? */
-- size_t cbBufReq = offStdErrBuf + cbRead + 1;
-- if ( cbBufReq > cbStdErrBuf
-- && cbBufReq < _256K)
-- {
-- size_t cbNew = RT_ALIGN_Z(cbBufReq, 16); // 1024
-- void *pvNew = RTMemRealloc(pszStdErrBuf, cbNew);
-- if (pvNew)
-- {
-- pszStdErrBuf = (char *)pvNew;
-- cbStdErrBuf = cbNew;
-- }
-- }
--
-- /* append if we've got room. */
-- if (cbBufReq <= cbStdErrBuf)
-- {
-- memcpy(&pszStdErrBuf[offStdErrBuf], achBuf, cbRead);
-- offStdErrBuf = offStdErrBuf + cbRead;
-- pszStdErrBuf[offStdErrBuf] = '\0';
-- }
-- }
-- else
-- {
-- AssertLogRelMsg(vrc == VERR_BROKEN_PIPE, ("%Rrc\n", vrc));
-- RTPipeClose(hPipeR);
-- hPipeR = NIL_RTPIPE;
-- }
-- }
--
-- /*
-- * Service the process. Block if we have no pipe.
-- */
-- if (hProcess != NIL_RTPROCESS)
-- {
-- vrc = RTProcWait(hProcess,
-- hPipeR == NIL_RTPIPE ? RTPROCWAIT_FLAGS_BLOCK : RTPROCWAIT_FLAGS_NOBLOCK,
-- &ProcStatus);
-- if (RT_SUCCESS(vrc))
-- hProcess = NIL_RTPROCESS;
-- else
-- AssertLogRelMsgStmt(vrc == VERR_PROCESS_RUNNING, ("%Rrc\n", vrc), hProcess = NIL_RTPROCESS);
-- }
-- } while ( hPipeR != NIL_RTPIPE
-- || hProcess != NIL_RTPROCESS);
--
-- LogRel(("ExtPack: enmReason=%d iStatus=%d stderr='%s'\n",
-- ProcStatus.enmReason, ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : ""));
--
-- /*
-- * Look for rcExit=RTEXITCODE_SUCCESS at the end of the error output,
-- * cut it as it is only there to attest the success.
-- */
-- if (offStdErrBuf > 0)
-- {
-- RTStrStripR(pszStdErrBuf);
-- offStdErrBuf = strlen(pszStdErrBuf);
-- }
--
-- char *pszSuccessInd = findSuccessIndicator(pszStdErrBuf, offStdErrBuf);
-- if (pszSuccessInd)
-- {
-- *pszSuccessInd = '\0';
-- offStdErrBuf = pszSuccessInd - pszStdErrBuf;
-- }
-- else if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL
-- && ProcStatus.iStatus == 0)
-- ProcStatus.iStatus = offStdErrBuf ? 667 : 666;
--
-- /*
-- * Compose the status code and, on failure, error message.
-- */
-- if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL
-- && ProcStatus.iStatus == 0)
-- hrc = S_OK;
-- else if (ProcStatus.enmReason == RTPROCEXITREASON_NORMAL)
-- {
-- AssertMsg(ProcStatus.iStatus != 0, ("%s\n", pszStdErrBuf));
-- hrc = setError(E_FAIL, tr("The installer failed with exit code %d: %s"),
-- ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
-- }
-- else if (ProcStatus.enmReason == RTPROCEXITREASON_SIGNAL)
-- hrc = setError(E_UNEXPECTED, tr("The installer was killed by signal #d (stderr: %s)"),
-- ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
-- else if (ProcStatus.enmReason == RTPROCEXITREASON_ABEND)
-- hrc = setError(E_UNEXPECTED, tr("The installer aborted abnormally (stderr: %s)"),
-- offStdErrBuf ? pszStdErrBuf : "");
-- else
-- hrc = setError(E_UNEXPECTED, tr("internal error: enmReason=%d iStatus=%d stderr='%s'"),
-- ProcStatus.enmReason, ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
--
-- RTMemFree(pszStdErrBuf);
-- }
-- else
-- hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to launch the helper application '%s' (%Rrc)"), szExecName, vrc);
--
-- RTPipeClose(hPipeR);
-- RTPipeClose(hStdErrPipe.u.hPipe);
--
-- return hrc;
--}
--
--/**
-- * Finds an installed extension pack.
-- *
-- * @returns Pointer to the extension pack if found, NULL if not. (No reference
-- * counting problem here since the caller must be holding the lock.)
-- * @param a_pszName The name of the extension pack.
-- */
--ExtPack *ExtPackManager::findExtPack(const char *a_pszName)
--{
-- size_t cchName = strlen(a_pszName);
--
-- for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
-- it != m->llInstalledExtPacks.end();
-- it++)
-- {
-- ExtPack::Data *pExtPackData = (*it)->m;
-- if ( pExtPackData
-- && pExtPackData->Desc.strName.length() == cchName
-- && pExtPackData->Desc.strName.equalsIgnoreCase(a_pszName))
-- return (*it);
-- }
-- return NULL;
--}
--
--/**
-- * Removes an installed extension pack from the internal list.
-- *
-- * The package is expected to exist!
-- *
-- * @param a_pszName The name of the extension pack.
-- */
--void ExtPackManager::removeExtPack(const char *a_pszName)
--{
-- size_t cchName = strlen(a_pszName);
--
-- for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
-- it != m->llInstalledExtPacks.end();
-- it++)
-- {
-- ExtPack::Data *pExtPackData = (*it)->m;
-- if ( pExtPackData
-- && pExtPackData->Desc.strName.length() == cchName
-- && pExtPackData->Desc.strName.equalsIgnoreCase(a_pszName))
-- {
-- m->llInstalledExtPacks.erase(it);
-- return;
-- }
-- }
-- AssertMsgFailed(("%s\n", a_pszName));
--}
--
--/**
-- * Refreshes the specified extension pack.
-- *
-- * This may remove the extension pack from the list, so any non-smart pointers
-- * to the extension pack object may become invalid.
-- *
-- * @returns S_OK and *a_ppExtPack on success, COM status code and error
-- * message on failure. Note that *a_ppExtPack can be NULL.
-- *
-- * @param a_pszName The extension to update..
-- * @param a_fUnusableIsError If @c true, report an unusable extension pack
-- * as an error.
-- * @param a_ppExtPack Where to store the pointer to the extension
-- * pack of it is still around after the refresh.
-- * This is optional.
-- *
-- * @remarks Caller holds the extension manager lock.
-- * @remarks Only called in VBoxSVC.
-- */
--HRESULT ExtPackManager::refreshExtPack(const char *a_pszName, bool a_fUnusableIsError, ExtPack **a_ppExtPack)
--{
-- Assert(m->pVirtualBox != NULL); /* Only called from VBoxSVC. */
--
-- HRESULT hrc;
-- ExtPack *pExtPack = findExtPack(a_pszName);
-- if (pExtPack)
-- {
-- /*
-- * Refresh existing object.
-- */
-- bool fCanDelete;
-- hrc = pExtPack->refresh(&fCanDelete);
-- if (SUCCEEDED(hrc))
-- {
-- if (fCanDelete)
-- {
-- removeExtPack(a_pszName);
-- pExtPack = NULL;
-- }
-- }
-- }
-- else
-- {
-- /*
-- * Do this check here, otherwise VBoxExtPackCalcDir() will fail with a strange
-- * error.
-- */
-- bool fValid = VBoxExtPackIsValidName(a_pszName);
-- if (!fValid)
-- return setError(E_FAIL, "Invalid extension pack name specified");
--
-- /*
-- * Does the dir exist? Make some special effort to deal with case
-- * sensitivie file systems (a_pszName is case insensitive and mangled).
-- */
-- char szDir[RTPATH_MAX];
-- int vrc = VBoxExtPackCalcDir(szDir, sizeof(szDir), m->strBaseDir.c_str(), a_pszName);
-- AssertLogRelRCReturn(vrc, E_FAIL);
--
-- RTDIRENTRYEX Entry;
-- RTFSOBJINFO ObjInfo;
-- vrc = RTPathQueryInfoEx(szDir, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
-- bool fExists = RT_SUCCESS(vrc) && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode);
-- if (!fExists)
-- {
-- PRTDIR pDir;
-- vrc = RTDirOpen(&pDir, m->strBaseDir.c_str());
-- if (RT_SUCCESS(vrc))
-- {
-- const char *pszMangledName = RTPathFilename(szDir);
-- for (;;)
-- {
-- vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
-- if (RT_FAILURE(vrc))
-- {
-- AssertLogRelMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
-- break;
-- }
-- if ( RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)
-- && !RTStrICmp(Entry.szName, pszMangledName))
-- {
-- /*
-- * The installed extension pack has a uses different case.
-- * Update the name and directory variables.
-- */
-- vrc = RTPathJoin(szDir, sizeof(szDir), m->strBaseDir.c_str(), Entry.szName); /* not really necessary */
-- AssertLogRelRCReturnStmt(vrc, RTDirClose(pDir), E_UNEXPECTED);
-- a_pszName = Entry.szName;
-- fExists = true;
-- break;
-- }
-- }
-- RTDirClose(pDir);
-- }
-- }
-- if (fExists)
-- {
-- /*
-- * We've got something, create a new extension pack object for it.
-- */
-- ComObjPtr<ExtPack> ptrNewExtPack;
-- hrc = ptrNewExtPack.createObject();
-- if (SUCCEEDED(hrc))
-- hrc = ptrNewExtPack->initWithDir(m->enmContext, a_pszName, szDir);
-- if (SUCCEEDED(hrc))
-- {
-- m->llInstalledExtPacks.push_back(ptrNewExtPack);
-- if (ptrNewExtPack->m->fUsable)
-- LogRel(("ExtPackManager: Found extension pack '%s'.\n", a_pszName));
-- else
-- LogRel(("ExtPackManager: Found bad extension pack '%s': %s\n",
-- a_pszName, ptrNewExtPack->m->strWhyUnusable.c_str() ));
-- pExtPack = ptrNewExtPack;
-- }
-- }
-- else
-- hrc = S_OK;
-- }
--
-- /*
-- * Report error if not usable, if that is desired.
-- */
-- if ( SUCCEEDED(hrc)
-- && pExtPack
-- && a_fUnusableIsError
-- && !pExtPack->m->fUsable)
-- hrc = setError(E_FAIL, "%s", pExtPack->m->strWhyUnusable.c_str());
--
-- if (a_ppExtPack)
-- *a_ppExtPack = pExtPack;
-- return hrc;
--}
--
--/**
-- * Thread wrapper around doInstall.
-- *
-- * @returns VINF_SUCCESS (ignored)
-- * @param hThread The thread handle (ignored).
-- * @param pvJob The job structure.
-- */
--/*static*/ DECLCALLBACK(int) ExtPackManager::doInstallThreadProc(RTTHREAD hThread, void *pvJob)
--{
-- PEXTPACKINSTALLJOB pJob = (PEXTPACKINSTALLJOB)pvJob;
-- HRESULT hrc = pJob->ptrExtPackMgr->doInstall(pJob->ptrExtPackFile, pJob->fReplace, &pJob->strDisplayInfo);
-- pJob->ptrProgress->notifyComplete(hrc);
-- delete pJob;
--
-- NOREF(hThread);
-- return VINF_SUCCESS;
--}
--
--/**
-- * Worker for IExtPackFile::Install.
-- *
-- * Called on a worker thread via doInstallThreadProc.
-- *
-- * @returns COM status code.
-- * @param a_pExtPackFile The extension pack file, caller checks that
-- * it's usable.
-- * @param a_fReplace Whether to replace any existing extpack or just
-- * fail.
-- * @param a_pstrDisplayInfo Host specific display information hacks.
-- * @param a_ppProgress Where to return a progress object some day. Can
-- * be NULL.
-- */
--HRESULT ExtPackManager::doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo)
--{
-- AssertReturn(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON, E_UNEXPECTED);
-- RTCString const * const pStrName = &a_pExtPackFile->m->Desc.strName;
-- RTCString const * const pStrTarball = &a_pExtPackFile->m->strExtPackFile;
-- RTCString const * const pStrTarballDigest = &a_pExtPackFile->m->strDigest;
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- /*
-- * Refresh the data we have on the extension pack as it
-- * may be made stale by direct meddling or some other user.
-- */
-- ExtPack *pExtPack;
-- hrc = refreshExtPack(pStrName->c_str(), false /*a_fUnusableIsError*/, &pExtPack);
-- if (SUCCEEDED(hrc))
-- {
-- if (pExtPack && a_fReplace)
-- hrc = pExtPack->callUninstallHookAndClose(m->pVirtualBox, false /*a_ForcedRemoval*/);
-- else if (pExtPack)
-- hrc = setError(E_FAIL,
-- tr("Extension pack '%s' is already installed."
-- " In case of a reinstallation, please uninstall it first"),
-- pStrName->c_str());
-- }
-- if (SUCCEEDED(hrc))
-- {
-- /*
-- * Run the privileged helper binary that performs the actual
-- * installation. Then create an object for the packet (we do this
-- * even on failure, to be on the safe side).
-- */
-- hrc = runSetUidToRootHelper(a_pstrDisplayInfo,
-- "install",
-- "--base-dir", m->strBaseDir.c_str(),
-- "--cert-dir", m->strCertificatDirPath.c_str(),
-- "--name", pStrName->c_str(),
-- "--tarball", pStrTarball->c_str(),
-- "--sha-256", pStrTarballDigest->c_str(),
-- pExtPack ? "--replace" : (const char *)NULL,
-- (const char *)NULL);
-- if (SUCCEEDED(hrc))
-- {
-- hrc = refreshExtPack(pStrName->c_str(), true /*a_fUnusableIsError*/, &pExtPack);
-- if (SUCCEEDED(hrc) && pExtPack)
-- {
-- RTERRINFOSTATIC ErrInfo;
-- RTErrInfoInitStatic(&ErrInfo);
-- pExtPack->callInstalledHook(m->pVirtualBox, &autoLock, &ErrInfo.Core);
-- if (RT_SUCCESS(ErrInfo.Core.rc))
-- LogRel(("ExtPackManager: Successfully installed extension pack '%s'.\n", pStrName->c_str()));
-- else
-- {
-- LogRel(("ExtPackManager: Installated hook for '%s' failed: %Rrc - %s\n",
-- pStrName->c_str(), ErrInfo.Core.rc, ErrInfo.Core.pszMsg));
--
-- /*
-- * Uninstall the extpack if the error indicates that.
-- */
-- if (ErrInfo.Core.rc == VERR_EXTPACK_UNSUPPORTED_HOST_UNINSTALL)
-- runSetUidToRootHelper(a_pstrDisplayInfo,
-- "uninstall",
-- "--base-dir", m->strBaseDir.c_str(),
-- "--name", pStrName->c_str(),
-- "--forced",
-- (const char *)NULL);
-- hrc = setError(E_FAIL, tr("The installation hook failed: %Rrc - %s"),
-- ErrInfo.Core.rc, ErrInfo.Core.pszMsg);
-- }
-- }
-- else if (SUCCEEDED(hrc))
-- hrc = setError(E_FAIL, tr("Installing extension pack '%s' failed under mysterious circumstances"),
-- pStrName->c_str());
-- }
-- else
-- {
-- ErrorInfoKeeper Eik;
-- refreshExtPack(pStrName->c_str(), false /*a_fUnusableIsError*/, NULL);
-- }
-- }
--
-- /*
-- * Do VirtualBoxReady callbacks now for any freshly installed
-- * extension pack (old ones will not be called).
-- */
-- if (m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON)
-- {
-- autoLock.release();
-- callAllVirtualBoxReadyHooks();
-- }
-- }
--
-- return hrc;
--}
--
--/**
-- * Thread wrapper around doUninstall.
-- *
-- * @returns VINF_SUCCESS (ignored)
-- * @param hThread The thread handle (ignored).
-- * @param pvJob The job structure.
-- */
--/*static*/ DECLCALLBACK(int) ExtPackManager::doUninstallThreadProc(RTTHREAD hThread, void *pvJob)
--{
-- PEXTPACKUNINSTALLJOB pJob = (PEXTPACKUNINSTALLJOB)pvJob;
-- HRESULT hrc = pJob->ptrExtPackMgr->doUninstall(&pJob->strName, pJob->fForcedRemoval, &pJob->strDisplayInfo);
-- pJob->ptrProgress->notifyComplete(hrc);
-- delete pJob;
--
-- NOREF(hThread);
-- return VINF_SUCCESS;
--}
--
--/**
-- * Worker for IExtPackManager::Uninstall.
-- *
-- * Called on a worker thread via doUninstallThreadProc.
-- *
-- * @returns COM status code.
-- * @param a_pstrName The name of the extension pack to uninstall.
-- * @param a_fForcedRemoval Whether to be skip and ignore certain bits of
-- * the extpack feedback. To deal with misbehaving
-- * extension pack hooks.
-- * @param a_pstrDisplayInfo Host specific display information hacks.
-- */
--HRESULT ExtPackManager::doUninstall(Utf8Str const *a_pstrName, bool a_fForcedRemoval, Utf8Str const *a_pstrDisplayInfo)
--{
-- Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- /*
-- * Refresh the data we have on the extension pack as it may be made
-- * stale by direct meddling or some other user.
-- */
-- ExtPack *pExtPack;
-- hrc = refreshExtPack(a_pstrName->c_str(), false /*a_fUnusableIsError*/, &pExtPack);
-- if (SUCCEEDED(hrc))
-- {
-- if (!pExtPack)
-- {
-- LogRel(("ExtPackManager: Extension pack '%s' is not installed, so nothing to uninstall.\n", a_pstrName->c_str()));
-- hrc = S_OK; /* nothing to uninstall */
-- }
-- else
-- {
-- /*
-- * Call the uninstall hook and unload the main dll.
-- */
-- hrc = pExtPack->callUninstallHookAndClose(m->pVirtualBox, a_fForcedRemoval);
-- if (SUCCEEDED(hrc))
-- {
-- /*
-- * Run the set-uid-to-root binary that performs the
-- * uninstallation. Then refresh the object.
-- *
-- * This refresh is theorically subject to races, but it's of
-- * the don't-do-that variety.
-- */
-- const char *pszForcedOpt = a_fForcedRemoval ? "--forced" : NULL;
-- hrc = runSetUidToRootHelper(a_pstrDisplayInfo,
-- "uninstall",
-- "--base-dir", m->strBaseDir.c_str(),
-- "--name", a_pstrName->c_str(),
-- pszForcedOpt, /* Last as it may be NULL. */
-- (const char *)NULL);
-- if (SUCCEEDED(hrc))
-- {
-- hrc = refreshExtPack(a_pstrName->c_str(), false /*a_fUnusableIsError*/, &pExtPack);
-- if (SUCCEEDED(hrc))
-- {
-- if (!pExtPack)
-- LogRel(("ExtPackManager: Successfully uninstalled extension pack '%s'.\n", a_pstrName->c_str()));
-- else
-- hrc = setError(E_FAIL,
-- tr("Uninstall extension pack '%s' failed under mysterious circumstances"),
-- a_pstrName->c_str());
-- }
-- }
-- else
-- {
-- ErrorInfoKeeper Eik;
-- refreshExtPack(a_pstrName->c_str(), false /*a_fUnusableIsError*/, NULL);
-- }
-- }
-- }
-- }
--
-- /*
-- * Do VirtualBoxReady callbacks now for any freshly installed
-- * extension pack (old ones will not be called).
-- */
-- if (m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON)
-- {
-- autoLock.release();
-- callAllVirtualBoxReadyHooks();
-- }
-- }
--
-- return hrc;
--}
--
--
--/**
-- * Calls the pfnVirtualBoxReady hook for all working extension packs.
-- *
-- * @remarks The caller must not hold any locks.
-- */
--void ExtPackManager::callAllVirtualBoxReadyHooks(void)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return;
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- ComPtr<ExtPackManager> ptrSelfRef = this;
--
-- for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
-- it != m->llInstalledExtPacks.end();
-- /* advancing below */)
-- {
-- if ((*it)->callVirtualBoxReadyHook(m->pVirtualBox, &autoLock))
-- it = m->llInstalledExtPacks.begin();
-- else
-- it++;
-- }
--}
--
--/**
-- * Calls the pfnConsoleReady hook for all working extension packs.
-- *
-- * @param a_pConsole The console interface.
-- * @remarks The caller must not hold any locks.
-- */
--void ExtPackManager::callAllConsoleReadyHooks(IConsole *a_pConsole)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return;
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- ComPtr<ExtPackManager> ptrSelfRef = this;
--
-- for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
-- it != m->llInstalledExtPacks.end();
-- /* advancing below */)
-- {
-- if ((*it)->callConsoleReadyHook(a_pConsole, &autoLock))
-- it = m->llInstalledExtPacks.begin();
-- else
-- it++;
-- }
--}
--
--/**
-- * Calls the pfnVMCreated hook for all working extension packs.
-- *
-- * @param a_pMachine The machine interface of the new VM.
-- */
--void ExtPackManager::callAllVmCreatedHooks(IMachine *a_pMachine)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return;
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- ComPtr<ExtPackManager> ptrSelfRef = this; /* paranoia */
-- ExtPackList llExtPacks = m->llInstalledExtPacks;
--
-- for (ExtPackList::iterator it = llExtPacks.begin(); it != llExtPacks.end(); it++)
-- (*it)->callVmCreatedHook(m->pVirtualBox, a_pMachine, &autoLock);
--}
--
--/**
-- * Calls the pfnVMConfigureVMM hook for all working extension packs.
-- *
-- * @returns VBox status code. Stops on the first failure, expecting the caller
-- * to signal this to the caller of the CFGM constructor.
-- * @param a_pConsole The console interface for the VM.
-- * @param a_pVM The VM handle.
-- */
--int ExtPackManager::callAllVmConfigureVmmHooks(IConsole *a_pConsole, PVM a_pVM)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return Global::vboxStatusCodeFromCOM(hrc);
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- ComPtr<ExtPackManager> ptrSelfRef = this; /* paranoia */
-- ExtPackList llExtPacks = m->llInstalledExtPacks;
--
-- for (ExtPackList::iterator it = llExtPacks.begin(); it != llExtPacks.end(); it++)
-- {
-- int vrc;
-- (*it)->callVmConfigureVmmHook(a_pConsole, a_pVM, &autoLock, &vrc);
-- if (RT_FAILURE(vrc))
-- return vrc;
-- }
--
-- return VINF_SUCCESS;
--}
--
--/**
-- * Calls the pfnVMPowerOn hook for all working extension packs.
-- *
-- * @returns VBox status code. Stops on the first failure, expecting the caller
-- * to not power on the VM.
-- * @param a_pConsole The console interface for the VM.
-- * @param a_pVM The VM handle.
-- */
--int ExtPackManager::callAllVmPowerOnHooks(IConsole *a_pConsole, PVM a_pVM)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return Global::vboxStatusCodeFromCOM(hrc);
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- ComPtr<ExtPackManager> ptrSelfRef = this; /* paranoia */
-- ExtPackList llExtPacks = m->llInstalledExtPacks;
--
-- for (ExtPackList::iterator it = llExtPacks.begin(); it != llExtPacks.end(); it++)
-- {
-- int vrc;
-- (*it)->callVmPowerOnHook(a_pConsole, a_pVM, &autoLock, &vrc);
-- if (RT_FAILURE(vrc))
-- return vrc;
-- }
--
-- return VINF_SUCCESS;
--}
--
--/**
-- * Calls the pfnVMPowerOff hook for all working extension packs.
-- *
-- * @param a_pConsole The console interface for the VM.
-- * @param a_pVM The VM handle. Can be NULL.
-- */
--void ExtPackManager::callAllVmPowerOffHooks(IConsole *a_pConsole, PVM a_pVM)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return;
-- AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
-- ComPtr<ExtPackManager> ptrSelfRef = this; /* paranoia */
-- ExtPackList llExtPacks = m->llInstalledExtPacks;
--
-- for (ExtPackList::iterator it = llExtPacks.begin(); it != llExtPacks.end(); it++)
-- (*it)->callVmPowerOffHook(a_pConsole, a_pVM, &autoLock);
--}
--
--
--/**
-- * Checks that the specified extension pack contains a VRDE module and that it
-- * is shipshape.
-- *
-- * @returns S_OK if ok, appropriate failure status code with details.
-- * @param a_pstrExtPack The name of the extension pack.
-- */
--HRESULT ExtPackManager::checkVrdeExtPack(Utf8Str const *a_pstrExtPack)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- ExtPack *pExtPack = findExtPack(a_pstrExtPack->c_str());
-- if (pExtPack)
-- hrc = pExtPack->checkVrde();
-- else
-- hrc = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No extension pack by the name '%s' was found"), a_pstrExtPack->c_str());
-- }
--
-- return hrc;
--}
--
--/**
-- * Gets the full path to the VRDE library of the specified extension pack.
-- *
-- * This will do extacly the same as checkVrdeExtPack and then resolve the
-- * library path.
-- *
-- * @returns S_OK if a path is returned, COM error status and message return if
-- * not.
-- * @param a_pstrExtPack The extension pack.
-- * @param a_pstrVrdeLibrary Where to return the path.
-- */
--int ExtPackManager::getVrdeLibraryPathForExtPack(Utf8Str const *a_pstrExtPack, Utf8Str *a_pstrVrdeLibrary)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- ExtPack *pExtPack = findExtPack(a_pstrExtPack->c_str());
-- if (pExtPack)
-- hrc = pExtPack->getVrdpLibraryName(a_pstrVrdeLibrary);
-- else
-- hrc = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No extension pack by the name '%s' was found"), a_pstrExtPack->c_str());
-- }
--
-- return hrc;
--}
--
--/**
-- * Gets the name of the default VRDE extension pack.
-- *
-- * @returns S_OK or some COM error status on red tape failure.
-- * @param a_pstrExtPack Where to return the extension pack name. Returns
-- * empty if no extension pack wishes to be the default
-- * VRDP provider.
-- */
--HRESULT ExtPackManager::getDefaultVrdeExtPack(Utf8Str *a_pstrExtPack)
--{
-- a_pstrExtPack->setNull();
--
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (SUCCEEDED(hrc))
-- {
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
-- it != m->llInstalledExtPacks.end();
-- it++)
-- {
-- if ((*it)->wantsToBeDefaultVrde())
-- {
-- *a_pstrExtPack = (*it)->m->Desc.strName;
-- break;
-- }
-- }
-- }
-- return hrc;
--}
--
--/**
-- * Checks if an extension pack is (present and) usable.
-- *
-- * @returns @c true if it is, otherwise @c false.
-- * @param a_pszExtPack The name of the extension pack.
-- */
--bool ExtPackManager::isExtPackUsable(const char *a_pszExtPack)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return false;
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- ExtPack *pExtPack = findExtPack(a_pszExtPack);
-- return pExtPack != NULL
-- && pExtPack->m->fUsable;
--}
--
--/**
-- * Dumps all extension packs to the release log.
-- */
--void ExtPackManager::dumpAllToReleaseLog(void)
--{
-- AutoCaller autoCaller(this);
-- HRESULT hrc = autoCaller.rc();
-- if (FAILED(hrc))
-- return;
-- AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
--
-- LogRel(("Installed Extension Packs:\n"));
-- for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
-- it != m->llInstalledExtPacks.end();
-- it++)
-- {
-- ExtPack::Data *pExtPackData = (*it)->m;
-- if (pExtPackData)
-- {
-- if (pExtPackData->fUsable)
-- LogRel((" %s (Version: %s r%u%s%s; VRDE Module: %s)\n",
-- pExtPackData->Desc.strName.c_str(),
-- pExtPackData->Desc.strVersion.c_str(),
-- pExtPackData->Desc.uRevision,
-- pExtPackData->Desc.strEdition.isEmpty() ? "" : " ",
-- pExtPackData->Desc.strEdition.c_str(),
-- pExtPackData->Desc.strVrdeModule.c_str() ));
-- else
-- LogRel((" %s (Version: %s r%u%s%s; VRDE Module: %s unusable because of '%s')\n",
-- pExtPackData->Desc.strName.c_str(),
-- pExtPackData->Desc.strVersion.c_str(),
-- pExtPackData->Desc.uRevision,
-- pExtPackData->Desc.strEdition.isEmpty() ? "" : " ",
-- pExtPackData->Desc.strEdition.c_str(),
-- pExtPackData->Desc.strVrdeModule.c_str(),
-- pExtPackData->strWhyUnusable.c_str() ));
-- }
-- else
-- LogRel((" pExtPackData is NULL\n"));
-- }
--
-- if (!m->llInstalledExtPacks.size())
-- LogRel((" None installed!\n"));
--}
--
--/* vi: set tabstop=4 shiftwidth=4 expandtab: */
---- VirtualBox-4.2.0.orig/src/VBox/Main/src-all/ExtPackUtil.cpp 2012-07-18 05:57:58.000000000 -0300
-+++ /dev/null 2012-09-18 22:18:48.866734195 -0300
-@@ -1,1385 +0,0 @@
--/* $Id: ExtPackUtil.cpp 41783 2012-06-16 19:24:15Z vboxsync $ */
--/** @file
-- * VirtualBox Main - Extension Pack Utilities and definitions, VBoxC, VBoxSVC, ++.
-- */
--
--/*
-- * Copyright (C) 2010-2012 Oracle Corporation
-- *
-- * This file is part of VirtualBox Open Source Edition (OSE), as
-- * available from http://www.virtualbox.org. This file is free software;
-- * you can redistribute it and/or modify it under the terms of the GNU
-- * General Public License (GPL) as published by the Free Software
-- * Foundation, in version 2 as it comes in the "COPYING" file of the
-- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-- */
--
--
--/*******************************************************************************
--* Header Files *
--*******************************************************************************/
--#include "../include/ExtPackUtil.h"
--
--#include <iprt/ctype.h>
--#include <iprt/dir.h>
--#include <iprt/file.h>
--#include <iprt/manifest.h>
--#include <iprt/param.h>
--#include <iprt/path.h>
--#include <iprt/sha.h>
--#include <iprt/string.h>
--#include <iprt/vfs.h>
--#include <iprt/tar.h>
--#include <iprt/zip.h>
--#include <iprt/cpp/xml.h>
--
--#include <VBox/log.h>
--
--
--/**
-- * Worker for VBoxExtPackLoadDesc that loads the plug-in descriptors.
-- *
-- * @returns Same as VBoxExtPackLoadDesc.
-- * @param pVBoxExtPackElm
-- * @param pcPlugIns Where to return the number of plug-ins in the
-- * array.
-- * @param paPlugIns Where to return the plug-in descriptor array.
-- * (RTMemFree it even on failure)
-- */
--static RTCString *
--vboxExtPackLoadPlugInDescs(const xml::ElementNode *pVBoxExtPackElm,
-- uint32_t *pcPlugIns, PVBOXEXTPACKPLUGINDESC *paPlugIns)
--{
-- *pcPlugIns = 0;
-- *paPlugIns = NULL;
--
-- /** @todo plug-ins */
-- NOREF(pVBoxExtPackElm);
--
-- return NULL;
--}
--
--/**
-- * Clears the extension pack descriptor.
-- *
-- * @param a_pExtPackDesc The descriptor to clear.
-- */
--static void vboxExtPackClearDesc(PVBOXEXTPACKDESC a_pExtPackDesc)
--{
-- a_pExtPackDesc->strName.setNull();
-- a_pExtPackDesc->strDescription.setNull();
-- a_pExtPackDesc->strVersion.setNull();
-- a_pExtPackDesc->strEdition.setNull();
-- a_pExtPackDesc->uRevision = 0;
-- a_pExtPackDesc->strMainModule.setNull();
-- a_pExtPackDesc->strVrdeModule.setNull();
-- a_pExtPackDesc->cPlugIns = 0;
-- a_pExtPackDesc->paPlugIns = NULL;
-- a_pExtPackDesc->fShowLicense = false;
--}
--
--/**
-- * Initializes an extension pack descriptor so that it's safe to call free on
-- * it whatever happens later on.
-- *
-- * @param a_pExtPackDesc The descirptor to initialize.
-- */
--void VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc)
--{
-- vboxExtPackClearDesc(a_pExtPackDesc);
--}
--
--
--/**
-- * Load the extension pack descriptor from an XML document.
-- *
-- * @returns NULL on success, pointer to an error message on failure (caller
-- * deletes it).
-- * @param a_pDoc Pointer to the XML document.
-- * @param a_pExtPackDesc Where to store the extension pack descriptor.
-- */
--static RTCString *vboxExtPackLoadDescFromDoc(xml::Document *a_pDoc, PVBOXEXTPACKDESC a_pExtPackDesc)
--{
-- /*
-- * Get the main element and check its version.
-- */
-- const xml::ElementNode *pVBoxExtPackElm = a_pDoc->getRootElement();
-- if ( !pVBoxExtPackElm
-- || strcmp(pVBoxExtPackElm->getName(), "VirtualBoxExtensionPack") != 0)
-- return new RTCString("No VirtualBoxExtensionPack element");
--
-- RTCString strFormatVersion;
-- if (!pVBoxExtPackElm->getAttributeValue("version", strFormatVersion))
-- return new RTCString("Missing format version");
-- if (!strFormatVersion.equals("1.0"))
-- return &(new RTCString("Unsupported format version: "))->append(strFormatVersion);
--
-- /*
-- * Read and validate mandatory bits.
-- */
-- const xml::ElementNode *pNameElm = pVBoxExtPackElm->findChildElement("Name");
-- if (!pNameElm)
-- return new RTCString("The 'Name' element is missing");
-- const char *pszName = pNameElm->getValue();
-- if (!VBoxExtPackIsValidName(pszName))
-- return &(new RTCString("Invalid name: "))->append(pszName);
--
-- const xml::ElementNode *pDescElm = pVBoxExtPackElm->findChildElement("Description");
-- if (!pDescElm)
-- return new RTCString("The 'Description' element is missing");
-- const char *pszDesc = pDescElm->getValue();
-- if (!pszDesc || *pszDesc == '\0')
-- return new RTCString("The 'Description' element is empty");
-- if (strpbrk(pszDesc, "\n\r\t\v\b") != NULL)
-- return new RTCString("The 'Description' must not contain control characters");
--
-- const xml::ElementNode *pVersionElm = pVBoxExtPackElm->findChildElement("Version");
-- if (!pVersionElm)
-- return new RTCString("The 'Version' element is missing");
-- const char *pszVersion = pVersionElm->getValue();
-- if (!pszVersion || *pszVersion == '\0')
-- return new RTCString("The 'Version' element is empty");
-- if (!VBoxExtPackIsValidVersionString(pszVersion))
-- return &(new RTCString("Invalid version string: "))->append(pszVersion);
--
-- uint32_t uRevision;
-- if (!pVersionElm->getAttributeValue("revision", uRevision))
-- uRevision = 0;
--
-- const char *pszEdition;
-- if (!pVersionElm->getAttributeValue("edition", pszEdition))
-- pszEdition = "";
-- if (!VBoxExtPackIsValidEditionString(pszEdition))
-- return &(new RTCString("Invalid edition string: "))->append(pszEdition);
--
-- const xml::ElementNode *pMainModuleElm = pVBoxExtPackElm->findChildElement("MainModule");
-- if (!pMainModuleElm)
-- return new RTCString("The 'MainModule' element is missing");
-- const char *pszMainModule = pMainModuleElm->getValue();
-- if (!pszMainModule || *pszMainModule == '\0')
-- return new RTCString("The 'MainModule' element is empty");
-- if (!VBoxExtPackIsValidModuleString(pszMainModule))
-- return &(new RTCString("Invalid main module string: "))->append(pszMainModule);
--
-- /*
-- * The VRDE module, optional.
-- * Accept both none and empty as tokens of no VRDE module.
-- */
-- const char *pszVrdeModule = NULL;
-- const xml::ElementNode *pVrdeModuleElm = pVBoxExtPackElm->findChildElement("VRDEModule");
-- if (pVrdeModuleElm)
-- {
-- pszVrdeModule = pVrdeModuleElm->getValue();
-- if (!pszVrdeModule || *pszVrdeModule == '\0')
-- pszVrdeModule = NULL;
-- else if (!VBoxExtPackIsValidModuleString(pszVrdeModule))
-- return &(new RTCString("Invalid VRDE module string: "))->append(pszVrdeModule);
-- }
--
-- /*
-- * Whether to show the license, optional. (presense is enough here)
-- */
-- const xml::ElementNode *pShowLicenseElm = pVBoxExtPackElm->findChildElement("ShowLicense");
-- bool fShowLicense = pShowLicenseElm != NULL;
--
-- /*
-- * Parse plug-in descriptions (last because of the manual memory management).
-- */
-- uint32_t cPlugIns = 0;
-- PVBOXEXTPACKPLUGINDESC paPlugIns = NULL;
-- RTCString *pstrRet = vboxExtPackLoadPlugInDescs(pVBoxExtPackElm, &cPlugIns, &paPlugIns);
-- if (pstrRet)
-- {
-- RTMemFree(paPlugIns);
-- return pstrRet;
-- }
--
-- /*
-- * Everything seems fine, fill in the return values and return successfully.
-- */
-- a_pExtPackDesc->strName = pszName;
-- a_pExtPackDesc->strDescription = pszDesc;
-- a_pExtPackDesc->strVersion = pszVersion;
-- a_pExtPackDesc->strEdition = pszEdition;
-- a_pExtPackDesc->uRevision = uRevision;
-- a_pExtPackDesc->strMainModule = pszMainModule;
-- a_pExtPackDesc->strVrdeModule = pszVrdeModule;
-- a_pExtPackDesc->cPlugIns = cPlugIns;
-- a_pExtPackDesc->paPlugIns = paPlugIns;
-- a_pExtPackDesc->fShowLicense = fShowLicense;
--
-- return NULL;
--}
--
--/**
-- * Reads the extension pack descriptor.
-- *
-- * @returns NULL on success, pointer to an error message on failure (caller
-- * deletes it).
-- * @param a_pszDir The directory containing the description file.
-- * @param a_pExtPackDesc Where to store the extension pack descriptor.
-- * @param a_pObjInfo Where to store the object info for the file (unix
-- * attribs). Optional.
-- */
--RTCString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo)
--{
-- vboxExtPackClearDesc(a_pExtPackDesc);
--
-- /*
-- * Validate, open and parse the XML file.
-- */
-- char szFilePath[RTPATH_MAX];
-- int vrc = RTPathJoin(szFilePath, sizeof(szFilePath), a_pszDir, VBOX_EXTPACK_DESCRIPTION_NAME);
-- if (RT_FAILURE(vrc))
-- return new RTCString("RTPathJoin failed with %Rrc", vrc);
--
-- RTFSOBJINFO ObjInfo;
-- vrc = RTPathQueryInfoEx(szFilePath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
-- if (RT_FAILURE(vrc))
-- return &(new RTCString())->printf("RTPathQueryInfoEx failed with %Rrc", vrc);
-- if (a_pObjInfo)
-- *a_pObjInfo = ObjInfo;
-- if (!RTFS_IS_FILE(ObjInfo.Attr.fMode))
-- {
-- if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
-- return new RTCString("The XML file is symlinked, that is not allowed");
-- return &(new RTCString)->printf("The XML file is not a file (fMode=%#x)", ObjInfo.Attr.fMode);
-- }
--
-- xml::Document Doc;
-- {
-- xml::XmlFileParser Parser;
-- try
-- {
-- Parser.read(szFilePath, Doc);
-- }
-- catch (xml::XmlError Err)
-- {
-- return new RTCString(Err.what());
-- }
-- }
--
-- /*
-- * Hand the xml doc over to the common code.
-- */
-- return vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);
--}
--
--/**
-- * Reads the extension pack descriptor.
-- *
-- * @returns NULL on success, pointer to an error message on failure (caller
-- * deletes it).
-- * @param a_pszDir The directory containing the description file.
-- * @param a_pExtPackDesc Where to store the extension pack descriptor.
-- * @param a_pObjInfo Where to store the object info for the file (unix
-- * attribs). Optional.
-- */
--RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo)
--{
-- vboxExtPackClearDesc(a_pExtPackDesc);
--
-- /*
-- * Query the object info.
-- */
-- RTFSOBJINFO ObjInfo;
-- int rc = RTVfsFileQueryInfo(hVfsFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
-- if (RT_FAILURE(rc))
-- return &(new RTCString)->printf("RTVfsFileQueryInfo failed: %Rrc", rc);
-- if (a_pObjInfo)
-- *a_pObjInfo = ObjInfo;
--
-- /*
-- * The simple approach, read the whole thing into memory and pass this to
-- * the XML parser.
-- */
--
-- /* Check the file size. */
-- if (ObjInfo.cbObject > _1M || ObjInfo.cbObject < 0)
-- return &(new RTCString)->printf("The XML file is too large (%'RU64 bytes)", ObjInfo.cbObject);
-- size_t const cbFile = (size_t)ObjInfo.cbObject;
--
-- /* Rewind to the start of the file. */
-- rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_BEGIN, NULL);
-- if (RT_FAILURE(rc))
-- return &(new RTCString)->printf("RTVfsFileSeek(,0,BEGIN) failed: %Rrc", rc);
--
-- /* Allocate memory and read the file content into it. */
-- void *pvFile = RTMemTmpAlloc(cbFile);
-- if (!pvFile)
-- return &(new RTCString)->printf("RTMemTmpAlloc(%zu) failed", cbFile);
--
-- RTCString *pstrErr = NULL;
-- rc = RTVfsFileRead(hVfsFile, pvFile, cbFile, NULL);
-- if (RT_FAILURE(rc))
-- pstrErr = &(new RTCString)->printf("RTVfsFileRead failed: %Rrc", rc);
--
-- /*
-- * Parse the file.
-- */
-- xml::Document Doc;
-- if (RT_SUCCESS(rc))
-- {
-- xml::XmlMemParser Parser;
-- RTCString strFileName = VBOX_EXTPACK_DESCRIPTION_NAME;
-- try
-- {
-- Parser.read(pvFile, cbFile, strFileName, Doc);
-- }
-- catch (xml::XmlError Err)
-- {
-- pstrErr = new RTCString(Err.what());
-- rc = VERR_PARSE_ERROR;
-- }
-- }
-- RTMemTmpFree(pvFile);
--
-- /*
-- * Hand the xml doc over to the common code.
-- */
-- if (RT_SUCCESS(rc))
-- pstrErr = vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);
--
-- return pstrErr;
--}
--
--/**
-- * Frees all resources associated with a extension pack descriptor.
-- *
-- * @param a_pExtPackDesc The extension pack descriptor which members
-- * should be freed.
-- */
--void VBoxExtPackFreeDesc(PVBOXEXTPACKDESC a_pExtPackDesc)
--{
-- if (!a_pExtPackDesc)
-- return;
--
-- a_pExtPackDesc->strName.setNull();
-- a_pExtPackDesc->strDescription.setNull();
-- a_pExtPackDesc->strVersion.setNull();
-- a_pExtPackDesc->strEdition.setNull();
-- a_pExtPackDesc->uRevision = 0;
-- a_pExtPackDesc->strMainModule.setNull();
-- a_pExtPackDesc->strVrdeModule.setNull();
-- a_pExtPackDesc->cPlugIns = 0;
-- RTMemFree(a_pExtPackDesc->paPlugIns);
-- a_pExtPackDesc->paPlugIns = NULL;
-- a_pExtPackDesc->fShowLicense = false;
--}
--
--/**
-- * Extract the extension pack name from the tarball path.
-- *
-- * @returns String containing the name on success, the caller must delete it.
-- * NULL if no valid name was found or if we ran out of memory.
-- * @param pszTarball The path to the tarball.
-- */
--RTCString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball)
--{
-- /*
-- * Skip ahead to the filename part and count the number of characters
-- * that matches the criteria for a mangled extension pack name.
-- */
-- const char *pszSrc = RTPathFilename(pszTarball);
-- if (!pszSrc)
-- return NULL;
--
-- size_t off = 0;
-- while (RT_C_IS_ALNUM(pszSrc[off]) || pszSrc[off] == '_')
-- off++;
--
-- /*
-- * Check min and max name limits.
-- */
-- if ( off > VBOX_EXTPACK_NAME_MAX_LEN
-- || off < VBOX_EXTPACK_NAME_MIN_LEN)
-- return NULL;
--
-- /*
-- * Return the unmangled name.
-- */
-- return VBoxExtPackUnmangleName(pszSrc, off);
--}
--
--/**
-- * Validates the extension pack name.
-- *
-- * @returns true if valid, false if not.
-- * @param pszName The name to validate.
-- * @sa VBoxExtPackExtractNameFromTarballPath
-- */
--bool VBoxExtPackIsValidName(const char *pszName)
--{
-- if (!pszName)
-- return false;
--
-- /*
-- * Check the characters making up the name, only english alphabet
-- * characters, decimal digits and spaces are allowed.
-- */
-- size_t off = 0;
-- while (pszName[off])
-- {
-- if (!RT_C_IS_ALNUM(pszName[off]) && pszName[off] != ' ')
-- return false;
-- off++;
-- }
--
-- /*
-- * Check min and max name limits.
-- */
-- if ( off > VBOX_EXTPACK_NAME_MAX_LEN
-- || off < VBOX_EXTPACK_NAME_MIN_LEN)
-- return false;
--
-- return true;
--}
--
--/**
-- * Checks if an alledged manged extension pack name.
-- *
-- * @returns true if valid, false if not.
-- * @param pszMangledName The mangled name to validate.
-- * @param cchMax The max number of chars to test.
-- * @sa VBoxExtPackMangleName
-- */
--bool VBoxExtPackIsValidMangledName(const char *pszMangledName, size_t cchMax /*= RTSTR_MAX*/)
--{
-- if (!pszMangledName)
-- return false;
--
-- /*
-- * Check the characters making up the name, only english alphabet
-- * characters, decimal digits and underscores (=space) are allowed.
-- */
-- size_t off = 0;
-- while (off < cchMax && pszMangledName[off])
-- {
-- if (!RT_C_IS_ALNUM(pszMangledName[off]) && pszMangledName[off] != '_')
-- return false;
-- off++;
-- }
--
-- /*
-- * Check min and max name limits.
-- */
-- if ( off > VBOX_EXTPACK_NAME_MAX_LEN
-- || off < VBOX_EXTPACK_NAME_MIN_LEN)
-- return false;
--
-- return true;
--}
--
--/**
-- * Mangle an extension pack name so it can be used by a directory or file name.
-- *
-- * @returns String containing the mangled name on success, the caller must
-- * delete it. NULL on failure.
-- * @param pszName The unmangled name.
-- * @sa VBoxExtPackUnmangleName, VBoxExtPackIsValidMangledName
-- */
--RTCString *VBoxExtPackMangleName(const char *pszName)
--{
-- AssertReturn(VBoxExtPackIsValidName(pszName), NULL);
--
-- char szTmp[VBOX_EXTPACK_NAME_MAX_LEN + 1];
-- size_t off = 0;
-- char ch;
-- while ((ch = pszName[off]) != '\0')
-- {
-- if (ch == ' ')
-- ch = '_';
-- szTmp[off++] = ch;
-- }
-- szTmp[off] = '\0';
-- Assert(VBoxExtPackIsValidMangledName(szTmp));
--
-- return new RTCString(szTmp, off);
--}
--
--/**
-- * Unmangle an extension pack name (reverses VBoxExtPackMangleName).
-- *
-- * @returns String containing the mangled name on success, the caller must
-- * delete it. NULL on failure.
-- * @param pszMangledName The mangled name.
-- * @param cchMax The max name length. RTSTR_MAX is fine.
-- * @sa VBoxExtPackMangleName, VBoxExtPackIsValidMangledName
-- */
--RTCString *VBoxExtPackUnmangleName(const char *pszMangledName, size_t cchMax)
--{
-- AssertReturn(VBoxExtPackIsValidMangledName(pszMangledName, cchMax), NULL);
--
-- char szTmp[VBOX_EXTPACK_NAME_MAX_LEN + 1];
-- size_t off = 0;
-- char ch;
-- while ( off < cchMax
-- && (ch = pszMangledName[off]) != '\0')
-- {
-- if (ch == '_')
-- ch = ' ';
-- else
-- AssertReturn(RT_C_IS_ALNUM(ch) || ch == ' ', NULL);
-- szTmp[off++] = ch;
-- }
-- szTmp[off] = '\0';
-- AssertReturn(VBoxExtPackIsValidName(szTmp), NULL);
--
-- return new RTCString(szTmp, off);
--}
--
--/**
-- * Constructs the extension pack directory path.
-- *
-- * A combination of RTPathJoin and VBoxExtPackMangleName.
-- *
-- * @returns IPRT status code like RTPathJoin.
-- * @param pszExtPackDir Where to return the directory path.
-- * @param cbExtPackDir The size of the return buffer.
-- * @param pszParentDir The parent directory (".../Extensions").
-- * @param pszName The extension pack name, unmangled.
-- */
--int VBoxExtPackCalcDir(char *pszExtPackDir, size_t cbExtPackDir, const char *pszParentDir, const char *pszName)
--{
-- AssertReturn(VBoxExtPackIsValidName(pszName), VERR_INTERNAL_ERROR_5);
--
-- RTCString *pstrMangledName = VBoxExtPackMangleName(pszName);
-- if (!pstrMangledName)
-- return VERR_INTERNAL_ERROR_4;
--
-- int vrc = RTPathJoin(pszExtPackDir, cbExtPackDir, pszParentDir, pstrMangledName->c_str());
-- delete pstrMangledName;
--
-- return vrc;
--}
--
--
--/**
-- * Validates the extension pack version string.
-- *
-- * @returns true if valid, false if not.
-- * @param pszVersion The version string to validate.
-- */
--bool VBoxExtPackIsValidVersionString(const char *pszVersion)
--{
-- if (!pszVersion || *pszVersion == '\0')
-- return false;
--
-- /* 1.x.y.z... */
-- for (;;)
-- {
-- if (!RT_C_IS_DIGIT(*pszVersion))
-- return false;
-- do
-- pszVersion++;
-- while (RT_C_IS_DIGIT(*pszVersion));
-- if (*pszVersion != '.')
-- break;
-- pszVersion++;
-- }
--
-- /* upper case string + numbers indicating the build type */
-- if (*pszVersion == '-' || *pszVersion == '_')
-- {
-- /** @todo Should probably restrict this to known build types (alpha,
-- * beta, rc, ++). */
-- do
-- pszVersion++;
-- while ( RT_C_IS_DIGIT(*pszVersion)
-- || RT_C_IS_UPPER(*pszVersion)
-- || *pszVersion == '-'
-- || *pszVersion == '_');
-- }
--
-- return *pszVersion == '\0';
--}
--
--/**
-- * Validates the extension pack edition string.
-- *
-- * @returns true if valid, false if not.
-- * @param pszEdition The edition string to validate.
-- */
--bool VBoxExtPackIsValidEditionString(const char *pszEdition)
--{
-- if (*pszEdition)
-- {
-- if (!RT_C_IS_UPPER(*pszEdition))
-- return false;
--
-- do
-- pszEdition++;
-- while ( RT_C_IS_UPPER(*pszEdition)
-- || RT_C_IS_DIGIT(*pszEdition)
-- || *pszEdition == '-'
-- || *pszEdition == '_');
-- }
-- return *pszEdition == '\0';
--}
--
--/**
-- * Validates an extension pack module string.
-- *
-- * @returns true if valid, false if not.
-- * @param pszModule The module string to validate.
-- */
--bool VBoxExtPackIsValidModuleString(const char *pszModule)
--{
-- if (!pszModule || *pszModule == '\0')
-- return false;
--
-- /* Restricted charset, no extensions (dots). */
-- while ( RT_C_IS_ALNUM(*pszModule)
-- || *pszModule == '-'
-- || *pszModule == '_')
-- pszModule++;
--
-- return *pszModule == '\0';
--}
--
--/**
-- * RTStrPrintfv wrapper.
-- *
-- * @returns @a rc
-- * @param rc The status code to return.
-- * @param pszError The error buffer.
-- * @param cbError The size of the buffer.
-- * @param pszFormat The error message format string.
-- * @param ... Format arguments.
-- */
--static int vboxExtPackReturnError(int rc, char *pszError, size_t cbError, const char *pszFormat, ...)
--{
-- va_list va;
-- va_start(va, pszFormat);
-- RTStrPrintfV(pszError, cbError, pszFormat, va);
-- va_end(va);
-- return rc;
--}
--
--/**
-- * RTStrPrintfv wrapper.
-- *
-- * @param pszError The error buffer.
-- * @param cbError The size of the buffer.
-- * @param pszFormat The error message format string.
-- * @param ... Format arguments.
-- */
--static void vboxExtPackSetError(char *pszError, size_t cbError, const char *pszFormat, ...)
--{
-- va_list va;
-- va_start(va, pszFormat);
-- RTStrPrintfV(pszError, cbError, pszFormat, va);
-- va_end(va);
--}
--
--/**
-- * Verifies the manifest and its signature.
-- *
-- * @returns VBox status code, failures with message.
-- * @param hManifestFile The xml from the extension pack.
-- * @param pszExtPackName The expected extension pack name. This can be
-- * NULL, in which we don't have any expectations.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- */
--static int vboxExtPackVerifyXml(RTVFSFILE hXmlFile, const char *pszExtPackName, char *pszError, size_t cbError)
--{
-- /*
-- * Load the XML.
-- */
-- VBOXEXTPACKDESC ExtPackDesc;
-- RTCString *pstrErr = VBoxExtPackLoadDescFromVfsFile(hXmlFile, &ExtPackDesc, NULL);
-- if (pstrErr)
-- {
-- RTStrCopy(pszError, cbError, pstrErr->c_str());
-- delete pstrErr;
-- return VERR_PARSE_ERROR;
-- }
--
-- /*
-- * Check the name.
-- */
-- /** @todo drop this restriction after the old install interface is
-- * dropped. */
-- int rc = VINF_SUCCESS;
-- if ( pszExtPackName
-- && !ExtPackDesc.strName.equalsIgnoreCase(pszExtPackName))
-- rc = vboxExtPackReturnError(VERR_NOT_EQUAL, pszError, cbError,
-- "The name of the downloaded file and the name stored inside the extension pack does not match"
-- " (xml='%s' file='%s')", ExtPackDesc.strName.c_str(), pszExtPackName);
-- return rc;
--}
--
--/**
-- * Verifies the manifest and its signature.
-- *
-- * @returns VBox status code, failures with message.
-- * @param hOurManifest The manifest we compiled.
-- * @param hManifestFile The manifest file in the extension pack.
-- * @param hSignatureFile The manifest signature file.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- */
--static int vboxExtPackVerifyManifestAndSignature(RTMANIFEST hOurManifest, RTVFSFILE hManifestFile, RTVFSFILE hSignatureFile,
-- char *pszError, size_t cbError)
--{
-- /*
-- * Read the manifest from the extension pack.
-- */
-- int rc = RTVfsFileSeek(hManifestFile, 0, RTFILE_SEEK_BEGIN, NULL);
-- if (RT_FAILURE(rc))
-- return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsFileSeek failed: %Rrc", rc);
--
-- RTMANIFEST hTheirManifest;
-- rc = RTManifestCreate(0 /*fFlags*/, &hTheirManifest);
-- if (RT_FAILURE(rc))
-- return vboxExtPackReturnError(rc, pszError, cbError, "RTManifestCreate failed: %Rrc", rc);
--
-- RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(hManifestFile);
-- rc = RTManifestReadStandard(hTheirManifest, hVfsIos);
-- RTVfsIoStrmRelease(hVfsIos);
-- if (RT_SUCCESS(rc))
-- {
-- /*
-- * Compare the manifests.
-- */
-- static const char *s_apszIgnoreEntries[] =
-- {
-- VBOX_EXTPACK_MANIFEST_NAME,
-- VBOX_EXTPACK_SIGNATURE_NAME,
-- "./" VBOX_EXTPACK_MANIFEST_NAME,
-- "./" VBOX_EXTPACK_SIGNATURE_NAME,
-- NULL
-- };
-- char szError[RTPATH_MAX];
-- rc = RTManifestEqualsEx(hOurManifest, hTheirManifest, &s_apszIgnoreEntries[0], NULL,
-- RTMANIFEST_EQUALS_IGN_MISSING_ATTRS /*fFlags*/,
-- szError, sizeof(szError));
-- if (RT_SUCCESS(rc))
-- {
-- /*
-- * Validate the manifest file signature.
-- */
-- /** @todo implement signature stuff */
-- NOREF(hSignatureFile);
--
-- }
-- else if (rc == VERR_NOT_EQUAL && szError[0])
-- vboxExtPackSetError(pszError, cbError, "Manifest mismatch: %s", szError);
-- else
-- vboxExtPackSetError(pszError, cbError, "RTManifestEqualsEx failed: %Rrc", rc);
--#if 0
-- RTVFSIOSTREAM hVfsIosStdOut = NIL_RTVFSIOSTREAM;
-- RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, true, &hVfsIosStdOut);
-- RTVfsIoStrmWrite(hVfsIosStdOut, "Our:\n", sizeof("Our:\n") - 1, true, NULL);
-- RTManifestWriteStandard(hOurManifest, hVfsIosStdOut);
-- RTVfsIoStrmWrite(hVfsIosStdOut, "Their:\n", sizeof("Their:\n") - 1, true, NULL);
-- RTManifestWriteStandard(hTheirManifest, hVfsIosStdOut);
--#endif
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "Error parsing '%s': %Rrc", VBOX_EXTPACK_MANIFEST_NAME, rc);
--
-- RTManifestRelease(hTheirManifest);
-- return rc;
--}
--
--
--/**
-- * Verifies the file digest (if specified) and returns the SHA-256 of the file.
-- *
-- * @returns
-- * @param hFileManifest Manifest containing a SHA-256 digest of the file
-- * that was calculated as the file was processed.
-- * @param pszFileDigest SHA-256 digest of the file.
-- * @param pStrDigest Where to return the SHA-256 digest. Optional.
-- * @param pszError Where to write an error message on failure.
-- * @param cbError The size of the @a pszError buffer.
-- */
--static int vboxExtPackVerifyFileDigest(RTMANIFEST hFileManifest, const char *pszFileDigest,
-- RTCString *pStrDigest, char *pszError, size_t cbError)
--{
-- /*
-- * Extract the SHA-256 entry for the extpack file.
-- */
-- char szCalculatedDigest[RTSHA256_DIGEST_LEN + 1];
-- int rc = RTManifestEntryQueryAttr(hFileManifest, "extpack", NULL /*no name*/, RTMANIFEST_ATTR_SHA256,
-- szCalculatedDigest, sizeof(szCalculatedDigest), NULL);
-- if (RT_SUCCESS(rc))
-- {
-- /*
-- * Convert the two strings to binary form before comparing.
-- * We convert the calculated hash even if we don't have anything to
-- * compare with, just to validate it.
-- */
-- uint8_t abCalculatedHash[RTSHA256_HASH_SIZE];
-- rc = RTSha256FromString(szCalculatedDigest, abCalculatedHash);
-- if (RT_SUCCESS(rc))
-- {
-- if ( pszFileDigest
-- && *pszFileDigest != '\0')
-- {
-- uint8_t abFileHash[RTSHA256_HASH_SIZE];
-- rc = RTSha256FromString(pszFileDigest, abFileHash);
-- if (RT_SUCCESS(rc))
-- {
-- if (memcmp(abFileHash, abCalculatedHash, sizeof(abFileHash)))
-- {
-- vboxExtPackSetError(pszError, cbError, "The extension pack file has changed (SHA-256 mismatch)");
-- rc = VERR_NOT_EQUAL;
-- }
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "Bad SHA-256 '%s': %Rrc", szCalculatedDigest, rc);
-- }
--
-- /*
-- * Set the output hash on success.
-- */
-- if (pStrDigest && RT_SUCCESS(rc))
-- {
-- try
-- {
-- *pStrDigest = szCalculatedDigest;
-- }
-- catch (std::bad_alloc)
-- {
-- rc = VERR_NO_MEMORY;
-- }
-- }
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "Bad SHA-256 '%s': %Rrc", szCalculatedDigest, rc);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTManifestEntryGetAttr: %Rrc", rc);
-- return rc;
--}
--
--
--
--/**
-- * Validates a standard file.
-- *
-- * Generally all files are
-- *
-- * @returns VBox status code, failure message in @a pszError.
-- * @param pszAdjName The adjusted member name.
-- * @param enmType The VFS object type.
-- * @param phVfsObj The pointer to the VFS object handle variable.
-- * This is both input and output.
-- * @param phVfsFile Where to store the handle to the memorized
-- * file. This is NULL for license files.
-- * @param pszError Where to write an error message on failure.
-- * @param cbError The size of the @a pszError buffer.
-- */
--static int VBoxExtPackValidateStandardFile(const char *pszAdjName, RTVFSOBJTYPE enmType,
-- PRTVFSOBJ phVfsObj, PRTVFSFILE phVfsFile, char *pszError, size_t cbError)
--{
-- int rc;
--
-- /*
-- * Make sure it's a file and that it isn't too large.
-- */
-- if (phVfsFile && *phVfsFile != NIL_RTVFSFILE)
-- rc = vboxExtPackReturnError(VERR_DUPLICATE, pszError, cbError,
-- "There can only be one '%s'", pszAdjName);
-- else if (enmType != RTVFSOBJTYPE_IO_STREAM && enmType != RTVFSOBJTYPE_FILE)
-- rc = vboxExtPackReturnError(VERR_NOT_A_FILE, pszError, cbError,
-- "Standard member '%s' is not a file", pszAdjName);
-- else
-- {
-- RTFSOBJINFO ObjInfo;
-- rc = RTVfsObjQueryInfo(*phVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING);
-- if (RT_SUCCESS(rc))
-- {
-- if (!RTFS_IS_FILE(ObjInfo.Attr.fMode))
-- rc = vboxExtPackReturnError(VERR_NOT_A_FILE, pszError, cbError,
-- "Standard member '%s' is not a file", pszAdjName);
-- else if (ObjInfo.cbObject >= _1M)
-- rc = vboxExtPackReturnError(VERR_OUT_OF_RANGE, pszError, cbError,
-- "Standard member '%s' is too large: %'RU64 bytes (max 1 MB)",
-- pszAdjName, (uint64_t)ObjInfo.cbObject);
-- else
-- {
-- /*
-- * Make an in memory copy of the stream and check that the file
-- * is UTF-8 clean.
-- */
-- RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(*phVfsObj);
-- RTVFSFILE hVfsFile;
-- rc = RTVfsMemorizeIoStreamAsFile(hVfsIos, RTFILE_O_READ, &hVfsFile);
-- if (RT_SUCCESS(rc))
-- {
-- rc = RTVfsIoStrmValidateUtf8Encoding(hVfsIos,
-- RTVFS_VALIDATE_UTF8_BY_RTC_3629 | RTVFS_VALIDATE_UTF8_NO_NULL,
-- NULL);
-- if (RT_SUCCESS(rc))
-- {
-- /*
-- * Replace *phVfsObj with the memorized file.
-- */
-- rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_BEGIN, NULL);
-- if (RT_SUCCESS(rc))
-- {
-- RTVfsObjRelease(*phVfsObj);
-- *phVfsObj = RTVfsObjFromFile(hVfsFile);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTVfsFileSeek failed on '%s': %Rrc", pszAdjName, rc);
-- }
--
-- if (phVfsFile && RT_SUCCESS(rc))
-- *phVfsFile = hVfsFile;
-- else
-- RTVfsFileRelease(hVfsFile);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTVfsMemorizeIoStreamAsFile failed on '%s': %Rrc", pszAdjName, rc);
-- RTVfsIoStrmRelease(hVfsIos);
-- }
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTVfsObjQueryInfo failed on '%s': %Rrc", pszAdjName, rc);
-- }
-- return rc;
--}
--
--
--/**
-- * Validates a name in an extension pack.
-- *
-- * We restrict the charset to try make sure the extension pack can be unpacked
-- * on all file systems.
-- *
-- * @returns VBox status code, failures with message.
-- * @param pszName The name to validate.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- */
--static int vboxExtPackValidateMemberName(const char *pszName, char *pszError, size_t cbError)
--{
-- if (RTPathStartsWithRoot(pszName))
-- return vboxExtPackReturnError(VERR_PATH_IS_NOT_RELATIVE, pszError, cbError, "'%s': starts with root spec", pszName);
--
-- const char *pszErr = NULL;
-- const char *psz = pszName;
-- int ch;
-- while ((ch = *psz) != '\0')
-- {
-- /* Character set restrictions. */
-- if (ch < 0 || ch >= 128)
-- {
-- pszErr = "Only 7-bit ASCII allowed";
-- break;
-- }
-- if (ch <= 31 || ch == 127)
-- {
-- pszErr = "No control characters are not allowed";
-- break;
-- }
-- if (ch == '\\')
-- {
-- pszErr = "Only backward slashes are not allowed";
-- break;
-- }
-- if (strchr("'\":;*?|[]<>(){}", ch))
-- {
-- pszErr = "The characters ', \", :, ;, *, ?, |, [, ], <, >, (, ), { and } are not allowed";
-- break;
-- }
--
-- /* Take the simple way out and ban all ".." sequences. */
-- if ( ch == '.'
-- && psz[1] == '.')
-- {
-- pszErr = "Double dot sequence are not allowed";
-- break;
-- }
--
-- /* Keep the tree shallow or the hardening checks will fail. */
-- if (psz - pszName > VBOX_EXTPACK_MAX_MEMBER_NAME_LENGTH)
-- {
-- pszErr = "Too long";
-- break;
-- }
--
-- /* advance */
-- psz++;
-- }
--
-- if (pszErr)
-- return vboxExtPackReturnError(VERR_INVALID_NAME, pszError, cbError,
-- "Bad member name '%s' (pos %zu): %s", pszName, (size_t)(psz - pszName), pszErr);
-- return RTEXITCODE_SUCCESS;
--}
--
--
--/**
-- * Validates a file in an extension pack.
-- *
-- * @returns VBox status code, failures with message.
-- * @param pszName The name of the file.
-- * @param hVfsObj The VFS object.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- */
--static int vboxExtPackValidateMemberFile(const char *pszName, RTVFSOBJ hVfsObj, char *pszError, size_t cbError)
--{
-- int rc = vboxExtPackValidateMemberName(pszName, pszError, cbError);
-- if (RT_SUCCESS(rc))
-- {
-- RTFSOBJINFO ObjInfo;
-- rc = RTVfsObjQueryInfo(hVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING);
-- if (RT_SUCCESS(rc))
-- {
-- if (ObjInfo.cbObject >= 9*_1G64)
-- rc = vboxExtPackReturnError(VERR_OUT_OF_RANGE, pszError, cbError,
-- "'%s': too large (%'RU64 bytes)",
-- pszName, (uint64_t)ObjInfo.cbObject);
-- if (!RTFS_IS_FILE(ObjInfo.Attr.fMode))
-- rc = vboxExtPackReturnError(VERR_NOT_A_FILE, pszError, cbError,
-- "The alleged file '%s' has a mode mask stating otherwise (%RTfmode)",
-- pszName, ObjInfo.Attr.fMode);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTVfsObjQueryInfo failed on '%s': %Rrc", pszName, rc);
-- }
-- return rc;
--}
--
--
--/**
-- * Validates a directory in an extension pack.
-- *
-- * @returns VBox status code, failures with message.
-- * @param pszName The name of the directory.
-- * @param hVfsObj The VFS object.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- */
--static int vboxExtPackValidateMemberDir(const char *pszName, RTVFSOBJ hVfsObj, char *pszError, size_t cbError)
--{
-- int rc = vboxExtPackValidateMemberName(pszName, pszError, cbError);
-- if (RT_SUCCESS(rc))
-- {
-- RTFSOBJINFO ObjInfo;
-- rc = RTVfsObjQueryInfo(hVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING);
-- if (RT_SUCCESS(rc))
-- {
-- if (!RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
-- rc = vboxExtPackReturnError(VERR_NOT_A_DIRECTORY, pszError, cbError,
-- "The alleged directory '%s' has a mode mask saying differently (%RTfmode)",
-- pszName, ObjInfo.Attr.fMode);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTVfsObjQueryInfo failed on '%s': %Rrc", pszName, rc);
-- }
-- return rc;
--}
--
--/**
-- * Validates a member of an extension pack.
-- *
-- * @returns VBox status code, failures with message.
-- * @param pszName The name of the directory.
-- * @param enmType The object type.
-- * @param hVfsObj The VFS object.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- */
--int VBoxExtPackValidateMember(const char *pszName, RTVFSOBJTYPE enmType, RTVFSOBJ hVfsObj, char *pszError, size_t cbError)
--{
-- Assert(cbError > 0);
-- *pszError = '\0';
--
-- int rc;
-- if ( enmType == RTVFSOBJTYPE_FILE
-- || enmType == RTVFSOBJTYPE_IO_STREAM)
-- rc = vboxExtPackValidateMemberFile(pszName, hVfsObj, pszError, cbError);
-- else if ( enmType == RTVFSOBJTYPE_DIR
-- || enmType == RTVFSOBJTYPE_BASE)
-- rc = vboxExtPackValidateMemberDir(pszName, hVfsObj, pszError, cbError);
-- else
-- rc = vboxExtPackReturnError(VERR_UNEXPECTED_FS_OBJ_TYPE, pszError, cbError,
-- "'%s' is not a file or directory (enmType=%d)", pszName, enmType);
-- return rc;
--}
--
--
--/**
-- * Rewinds the tarball file handle and creates a gunzip | tar chain that
-- * results in a filesystem stream.
-- *
-- * @returns VBox status code, failures with message.
-- * @param hTarballFile The handle to the tarball file.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- * @param phTarFss Where to return the filesystem stream handle.
-- * @param phFileManifest Where to return a manifest where the tarball is
-- * gettting hashed. The entry will be called
-- * "extpack" and be ready when the file system
-- * stream is at an end. Optional.
-- */
--int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss, PRTMANIFEST phFileManifest)
--{
-- Assert(cbError > 0);
-- *pszError = '\0';
-- *phTarFss = NIL_RTVFSFSSTREAM;
--
-- /*
-- * Rewind the file and set up a VFS chain for it.
-- */
-- int rc = RTFileSeek(hTarballFile, 0, RTFILE_SEEK_BEGIN, NULL);
-- if (RT_FAILURE(rc))
-- return vboxExtPackReturnError(rc, pszError, cbError, "Failed seeking to the start of the tarball: %Rrc", rc);
--
-- RTVFSIOSTREAM hTarballIos;
-- rc = RTVfsIoStrmFromRTFile(hTarballFile, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, true /*fLeaveOpen*/,
-- &hTarballIos);
-- if (RT_FAILURE(rc))
-- return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsIoStrmFromRTFile failed: %Rrc", rc);
--
-- RTMANIFEST hFileManifest = NIL_RTMANIFEST;
-- rc = RTManifestCreate(0 /*fFlags*/, &hFileManifest);
-- if (RT_SUCCESS(rc))
-- {
-- RTVFSIOSTREAM hPtIos;
-- rc = RTManifestEntryAddPassthruIoStream(hFileManifest, hTarballIos, "extpack", RTMANIFEST_ATTR_SHA256, true /*read*/, &hPtIos);
-- if (RT_SUCCESS(rc))
-- {
-- RTVFSIOSTREAM hGunzipIos;
-- rc = RTZipGzipDecompressIoStream(hPtIos, 0 /*fFlags*/, &hGunzipIos);
-- if (RT_SUCCESS(rc))
-- {
-- RTVFSFSSTREAM hTarFss;
-- rc = RTZipTarFsStreamFromIoStream(hGunzipIos, 0 /*fFlags*/, &hTarFss);
-- if (RT_SUCCESS(rc))
-- {
-- RTVfsIoStrmRelease(hPtIos);
-- RTVfsIoStrmRelease(hGunzipIos);
-- RTVfsIoStrmRelease(hTarballIos);
-- *phTarFss = hTarFss;
-- if (phFileManifest)
-- *phFileManifest = hFileManifest;
-- else
-- RTManifestRelease(hFileManifest);
-- return VINF_SUCCESS;
-- }
--
-- vboxExtPackSetError(pszError, cbError, "RTZipTarFsStreamFromIoStream failed: %Rrc", rc);
-- RTVfsIoStrmRelease(hGunzipIos);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTZipGzipDecompressIoStream failed: %Rrc", rc);
-- RTVfsIoStrmRelease(hPtIos);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTManifestEntryAddPassthruIoStream failed: %Rrc", rc);
-- RTManifestRelease(hFileManifest);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc);
--
-- RTVfsIoStrmRelease(hTarballIos);
-- return rc;
--}
--
--
--/**
-- * Validates the extension pack tarball prior to unpacking.
-- *
-- * Operations performed:
-- * - Mandatory files.
-- * - Manifest check.
-- * - Manifest seal check.
-- * - XML check, match name.
-- *
-- * @returns VBox status code, failures with message.
-- * @param hTarballFile The handle to open the @a pszTarball file.
-- * @param pszExtPackName The name of the extension pack name. NULL if
-- * the name is not fixed.
-- * @param pszTarball The name of the tarball in case we have to
-- * complain about something.
-- * @param pszTarballDigest The SHA-256 digest of the tarball. Empty string
-- * if no digest available.
-- * @param pszError Where to store an error message on failure.
-- * @param cbError The size of the buffer @a pszError points to.
-- * @param phValidManifest Where to optionally return the handle to fully
-- * validated the manifest for the extension pack.
-- * This includes all files.
-- * @param phXmlFile Where to optionally return the memorized XML
-- * file.
-- * @param pStrDigest Where to return the digest of the file.
-- * Optional.
-- */
--int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName,
-- const char *pszTarball, const char *pszTarballDigest,
-- char *pszError, size_t cbError,
-- PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile, RTCString *pStrDigest)
--{
-- /*
-- * Clear return values.
-- */
-- if (phValidManifest)
-- *phValidManifest = NIL_RTMANIFEST;
-- if (phXmlFile)
-- *phXmlFile = NIL_RTVFSFILE;
-- Assert(cbError > 1);
-- *pszError = '\0';
-- NOREF(pszTarball);
--
-- /*
-- * Open the tar.gz filesystem stream and set up an manifest in-memory file.
-- */
-- RTMANIFEST hFileManifest;
-- RTVFSFSSTREAM hTarFss;
-- int rc = VBoxExtPackOpenTarFss(hTarballFile, pszError, cbError, &hTarFss, &hFileManifest);
-- if (RT_FAILURE(rc))
-- return rc;
--
-- RTMANIFEST hOurManifest;
-- rc = RTManifestCreate(0 /*fFlags*/, &hOurManifest);
-- if (RT_SUCCESS(rc))
-- {
-- /*
-- * Process the tarball (would be nice to move this to a function).
-- */
-- RTVFSFILE hXmlFile = NIL_RTVFSFILE;
-- RTVFSFILE hManifestFile = NIL_RTVFSFILE;
-- RTVFSFILE hSignatureFile = NIL_RTVFSFILE;
-- for (;;)
-- {
-- /*
-- * Get the next stream object.
-- */
-- char *pszName;
-- RTVFSOBJ hVfsObj;
-- RTVFSOBJTYPE enmType;
-- rc = RTVfsFsStrmNext(hTarFss, &pszName, &enmType, &hVfsObj);
-- if (RT_FAILURE(rc))
-- {
-- if (rc != VERR_EOF)
-- vboxExtPackSetError(pszError, cbError, "RTVfsFsStrmNext failed: %Rrc", rc);
-- else
-- rc = VINF_SUCCESS;
-- break;
-- }
-- const char *pszAdjName = pszName[0] == '.' && pszName[1] == '/' ? &pszName[2] : pszName;
--
-- /*
-- * Check the type & name validity, performing special tests on
-- * standard extension pack member files.
-- *
-- * N.B. We will always reach the end of the loop before breaking on
-- * failure - cleanup reasons.
-- */
-- rc = VBoxExtPackValidateMember(pszName, enmType, hVfsObj, pszError, cbError);
-- if (RT_SUCCESS(rc))
-- {
-- PRTVFSFILE phVfsFile = NULL;
-- if (!strcmp(pszAdjName, VBOX_EXTPACK_DESCRIPTION_NAME))
-- phVfsFile = &hXmlFile;
-- else if (!strcmp(pszAdjName, VBOX_EXTPACK_MANIFEST_NAME))
-- phVfsFile = &hManifestFile;
-- else if (!strcmp(pszAdjName, VBOX_EXTPACK_SIGNATURE_NAME))
-- phVfsFile = &hSignatureFile;
-- else if (!strncmp(pszAdjName, VBOX_EXTPACK_LICENSE_NAME_PREFIX, sizeof(VBOX_EXTPACK_LICENSE_NAME_PREFIX) - 1))
-- rc = VBoxExtPackValidateStandardFile(pszAdjName, enmType, &hVfsObj, NULL, pszError, cbError);
-- if (phVfsFile)
-- rc = VBoxExtPackValidateStandardFile(pszAdjName, enmType, &hVfsObj, phVfsFile, pszError, cbError);
-- }
--
-- /*
-- * Add any I/O stream to the manifest
-- */
-- if ( RT_SUCCESS(rc)
-- && ( enmType == RTVFSOBJTYPE_FILE
-- || enmType == RTVFSOBJTYPE_IO_STREAM))
-- {
-- RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(hVfsObj);
-- rc = RTManifestEntryAddIoStream(hOurManifest, hVfsIos, pszAdjName, RTMANIFEST_ATTR_SIZE | RTMANIFEST_ATTR_SHA256);
-- if (RT_FAILURE(rc))
-- vboxExtPackSetError(pszError, cbError, "RTManifestEntryAddIoStream failed on '%s': %Rrc", pszAdjName, rc);
-- RTVfsIoStrmRelease(hVfsIos);
-- }
--
-- /*
-- * Clean up and break out on failure.
-- */
-- RTVfsObjRelease(hVfsObj);
-- RTStrFree(pszName);
-- if (RT_FAILURE(rc))
-- break;
-- }
--
-- /*
-- * Check the integrity of the tarball file.
-- */
-- if (RT_SUCCESS(rc))
-- {
-- RTVfsFsStrmRelease(hTarFss);
-- hTarFss = NIL_RTVFSFSSTREAM;
-- rc = vboxExtPackVerifyFileDigest(hFileManifest, pszTarballDigest, pStrDigest, pszError, cbError);
-- }
--
-- /*
-- * If we've successfully processed the tarball, verify that the
-- * mandatory files are present.
-- */
-- if (RT_SUCCESS(rc))
-- {
-- if (hXmlFile == NIL_RTVFSFILE)
-- rc = vboxExtPackReturnError(VERR_MISSING, pszError, cbError, "Mandator file '%s' is missing", VBOX_EXTPACK_DESCRIPTION_NAME);
-- if (hManifestFile == NIL_RTVFSFILE)
-- rc = vboxExtPackReturnError(VERR_MISSING, pszError, cbError, "Mandator file '%s' is missing", VBOX_EXTPACK_MANIFEST_NAME);
-- if (hSignatureFile == NIL_RTVFSFILE)
-- rc = vboxExtPackReturnError(VERR_MISSING, pszError, cbError, "Mandator file '%s' is missing", VBOX_EXTPACK_SIGNATURE_NAME);
-- }
--
-- /*
-- * Check the manifest and it's signature.
-- */
-- if (RT_SUCCESS(rc))
-- rc = vboxExtPackVerifyManifestAndSignature(hOurManifest, hManifestFile, hSignatureFile, pszError, cbError);
--
-- /*
-- * Check the XML.
-- */
-- if (RT_SUCCESS(rc))
-- rc = vboxExtPackVerifyXml(hXmlFile, pszExtPackName, pszError, cbError);
--
-- /*
-- * Returns objects.
-- */
-- if (RT_SUCCESS(rc))
-- {
-- if (phValidManifest)
-- {
-- RTManifestRetain(hOurManifest);
-- *phValidManifest = hOurManifest;
-- }
-- if (phXmlFile)
-- {
-- RTVfsFileRetain(hXmlFile);
-- *phXmlFile = hXmlFile;
-- }
-- }
--
-- /*
-- * Release our object references.
-- */
-- RTManifestRelease(hOurManifest);
-- RTVfsFileRelease(hXmlFile);
-- RTVfsFileRelease(hManifestFile);
-- RTVfsFileRelease(hSignatureFile);
-- }
-- else
-- vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc);
-- RTVfsFsStrmRelease(hTarFss);
-- RTManifestRelease(hFileManifest);
--
-- return rc;
--}
--
--- VirtualBox-4.1.18.orig/include/Makefile.kmk 2012-06-20 10:07:49.000000000 -0300
+++ VirtualBox-4.1.18/include/Makefile.kmk 2012-07-24 21:11:57.007068865 -0300
@@ -51,7 +51,6 @@
diff --git a/libre/virtualbox-libre/vboxbuild b/libre/virtualbox-libre/vboxbuild
deleted file mode 100755
index 27519950f..000000000
--- a/libre/virtualbox-libre/vboxbuild
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/bash
-
-. /etc/vbox/vbox.cfg
-
-MODLIST=()
-LOG="/var/log/vbox-install.log"
->| "$LOG"
-
-stat_busy() {
- printf '==> %s ... ' "$1"
-}
-
-stat_done() {
- echo 'done'
-}
-
-stat_fail() {
- echo 'failed'
-}
-
-if [[ $INSTALL_DIR ]]; then
- VBOXMANAGE=$INSTALL_DIR/VBoxManage
- BUILDVBOXDRV=$INSTALL_DIR/src/vboxdrv/build_in_tmp
- BUILDVBOXNETFLT=$INSTALL_DIR/src/vboxnetflt/build_in_tmp
- BUILDVBOXNETADP=$INSTALL_DIR/src/vboxnetadp/build_in_tmp
- BUILDVBOXPCI=$INSTALL_DIR/src/vboxpci/build_in_tmp
-else
- echo "error: missing vbox.cfg"
- exit 1
-fi
-
-if [[ -f /proc/modules ]]; then
- IFS=$'\n' read -r -d '' -a MODLIST < \
- <(grep -oE '^vbox(pci|netflt|netadp|drv)' /proc/modules)
-fi
-
-if (( ${#MODLIST[*]} )); then
- stat_busy "Unloading VirtualBox kernel libre modules"
- modprobe -ar "${MODLIST[@]}" && stat_done || stat_fail
-fi
-
-for kdir in /usr/lib/modules/[2-3]*; do
- if [[ ! -d $kdir/kernel ]]; then
- # found a stale kernel
- mods=("$kdir/extramodules"{drv,netadp,netflt,pci}.ko*)
- if (( ${#mods[@]} )); then
- stat_busy "Removing all old VirtualBox kernel libre modules"
- if rm -f "${mods[@]}" &&
- rmdir -p --ignore-fail-on-non-empty "$kdir/extramodules" 2>/dev/null; then
- stat_done
- else
- stat_fail
- fi
- fi
- fi
-done
-
-# default to the currently running kernel
-if (( ! $# )); then
- set -- $(uname -r)
-fi
-
-for kernver; do
- export KERN_DIR=/usr/lib/modules/$kernver/build
- export MODULE_DIR=/usr/lib/modules/$kernver/extramodules
- if [[ ! -d $KERN_DIR ]]; then
- printf "error: \`%s' does not appear to be a valid kernel libre build directory.\n" \
- "$KERN_DIR"
- continue
- fi
-
- stat_busy "Recompiling VirtualBox kernel libre modules ($kernver)"
- if ! $BUILDVBOXDRV \
- --save-module-symvers /tmp/vboxdrv-Module.symvers \
- --no-print-directory install >> $LOG 2>&1; then
- echo "Look at $LOG to find out what went wrong"
- stat_fail
- fi
- for build in BUILDVBOX{NETFLT,NETADP,PCI}; do
- if ! ${!build} \
- --use-module-symvers /tmp/vboxdrv-Module.symvers \
- --no-print-directory install >> $LOG 2>&1; then
- echo "Look at $LOG to find out what went wrong"
- stat_fail
- fi
- done
- gzip -f9 "$MODULE_DIR"/*.ko
- depmod "$kernver"
- stat_done
-done
-
-if (( ${#MODLIST[*]} )); then
- stat_busy "Reloading VirtualBox kernel libre modules"
- modprobe -a "${MODLIST[@]}" && stat_done || stat_fail
-fi
diff --git a/libre/xulrunner-libre/Bug-756390-Make-the-Reset-Firefox-feature-more-gener.patch b/libre/xulrunner-libre/Bug-756390-Make-the-Reset-Firefox-feature-more-gener.patch
index 240c3d4e8..a5fe02165 100755
--- a/libre/xulrunner-libre/Bug-756390-Make-the-Reset-Firefox-feature-more-gener.patch
+++ b/libre/xulrunner-libre/Bug-756390-Make-the-Reset-Firefox-feature-more-gener.patch
@@ -139,7 +139,7 @@ index 21cf405..f3c1a6b 100644
<!ENTITY noMigrationSources.label "No programs that contain bookmarks, history or password data could be found.">
diff --git a/browser/locales/en-US/chrome/browser/migration/migration.properties b/browser/locales/en-US/chrome/browser/migration/migration.properties
-index ab82d85..915f6b8 100644
+index 260bc29..52b32cc 100644
--- a/browser/locales/en-US/chrome/browser/migration/migration.properties
+++ b/browser/locales/en-US/chrome/browser/migration/migration.properties
@@ -8,7 +8,6 @@ profileName_format=%S %S
@@ -150,7 +150,7 @@ index ab82d85..915f6b8 100644
importedBookmarksFolder=From %S
-@@ -22,22 +21,22 @@ importedSafariReadingList=Reading List (From Safari)
+@@ -24,22 +23,22 @@ importedSafariReadingList=Reading List (From Safari)
2_ie=Cookies
2_safari=Cookies
2_chrome=Cookies
@@ -177,25 +177,25 @@ index ab82d85..915f6b8 100644
32_ie=Favorites
32_safari=Bookmarks
-@@ -46,4 +45,4 @@ importedSafariReadingList=Reading List (From Safari)
+@@ -48,4 +47,4 @@ importedSafariReadingList=Reading List (From Safari)
64_ie=Other Data
64_safari=Other Data
64_chrome=Other Data
-64_firefox=Bookmarks Backups
+64_self=Bookmarks Backups
diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
-index 697b217..b6e1709 100644
+index 339ffda..6999b26 100644
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -38,7 +38,7 @@ toolkit.jar:
+ content/global/mozilla.xhtml (mozilla.xhtml)
- *+ content/global/nsDragAndDrop.js (nsDragAndDrop.js)
+ content/global/nsDragAndDrop.js (nsDragAndDrop.js)
content/global/resetProfile.css (resetProfile.css)
-* content/global/resetProfile.js (resetProfile.js)
+ content/global/resetProfile.js (resetProfile.js)
- * content/global/resetProfile.xul (resetProfile.xul)
- * content/global/resetProfileProgress.xul (resetProfileProgress.xul)
- * content/global/treeUtils.js (treeUtils.js)
+ content/global/resetProfile.xul (resetProfile.xul)
+ content/global/resetProfileProgress.xul (resetProfileProgress.xul)
+ content/global/treeUtils.js (treeUtils.js)
diff --git a/toolkit/content/resetProfile.js b/toolkit/content/resetProfile.js
index dcb4065..09c1146 100644
--- a/toolkit/content/resetProfile.js
@@ -267,10 +267,10 @@ index f35c227..7062886 100644
%{C++
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
-index e5d3042..6de3390 100644
+index 60348b5..c240c4f 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
-@@ -3650,7 +3650,7 @@ XREMain::XRE_mainRun()
+@@ -3651,7 +3651,7 @@ XREMain::XRE_mainRun()
if (gDoProfileReset) {
// Automatically migrate from the current application if we just
// reset the profile.
diff --git a/libre/xulrunner-libre/PKGBUILD b/libre/xulrunner-libre/PKGBUILD
index 4c93e1c48..0d5f817e6 100755
--- a/libre/xulrunner-libre/PKGBUILD
+++ b/libre/xulrunner-libre/PKGBUILD
@@ -6,7 +6,7 @@
# We're getting this from Debian Experimental
_debname=iceweasel
-_debver=15.0.1
+_debver=16.0.1
_debrel=1
_debrepo=http://ftp.debian.org/debian/pool/main/
debfile() { echo $@|sed -r 's@(.).*@\1/&/&@'; }
@@ -30,11 +30,11 @@ options=('!emptydirs')
conflicts=('xulrunner')
provides=("xulrunner=${_debver}")
replaces=('xulrunner-oss' 'xulrunner')
-md5sums=('0936242388cd4c75930c1d2487e15216'
- 'ce37c76476b8edf40780d00cf79d0d62'
+md5sums=('33e50f7ddfa7274e5a3bd393c37fb3b3'
+ 'ddfcf225ea0e3d7b4b377f4a63d5e8c4'
'f2f4f4a573f549e8b494e33b3ad226bc'
'27271ce647a83906ef7a24605e840d61'
- 'c52fac65c1e06290a5108b75c31ace79')
+ '0a31239f1008038df5057982fe745dec')
build() {
export QUILT_PATCHES=debian/patches