diff --git a/.gitignore b/.gitignore
index 6148a29a95d0bcaa062cdf89beabb1a55386a24d..4b38dc02ac7d81f071a41dbecf00701eb5a555e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,4 @@ install/win32/meta.py
 /lib/
 /man/
 /share/
-/src/
+/src/
\ No newline at end of file
diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 61c397364b9e753e406a8c876fa2b2b5d471aa5c..fe701a85661243d37715fa6bdf2188e7f12a0c19 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -60,7 +60,7 @@
                         </group>
                         <group>
                             <field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view')]" name="account_id" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)" groups="account.group_account_user"/>
-                            <field name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
+                            <field name="invoice_line_tax_id" context="{'type':parent.get('type')}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
                             <field domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
                             <field name="company_id" groups="base.group_multi_company" readonly="1"/>
                         </group>
diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py
index 3fd83c19207090a3ef968b030a852b55999fbeb1..2e3c9b7c3748d2604c586cd4868e0b64133058b0 100644
--- a/addons/account/report/account_aged_partner_balance.py
+++ b/addons/account/report/account_aged_partner_balance.py
@@ -161,7 +161,7 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header):
                 dates_query += ' < %s)'
                 args_list += (form[str(i)]['stop'],)
             args_list += (self.date_from,)
-            self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit)
+            self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit), l.reconcile_partial_id
                     FROM account_move_line AS l, account_account, account_move am 
                     WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)
                         AND (am.state IN %s)
@@ -173,12 +173,24 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header):
                         AND account_account.active
                         AND ''' + dates_query + '''
                     AND (l.date <= %s)
-                    GROUP BY l.partner_id''', args_list)
-            t = self.cr.fetchall()
-            d = {}
-            for i in t:
-                d[i[0]] = i[1]
-            history.append(d)
+                    GROUP BY l.partner_id, l.reconcile_partial_id''', args_list)
+            partners_partial = self.cr.fetchall()
+            partners_amount = dict((i[0],0) for i in partners_partial)
+            for partner_info in partners_partial:
+                if partner_info[2]:
+                    # in case of partial reconciliation, we want to keep the left amount in the oldest period
+                    self.cr.execute('''SELECT MIN(COALESCE(date_maturity,date)) FROM account_move_line WHERE reconcile_partial_id = %s''', (partner_info[2],))
+                    date = self.cr.fetchall()
+                    if date and args_list[-3] <= date[0][0] <= args_list[-2]:
+                        # partial reconcilation
+                        self.cr.execute('''SELECT SUM(l.debit-l.credit)
+                                           FROM account_move_line AS l
+                                           WHERE l.reconcile_partial_id = %s''', (partner_info[2],))
+                        unreconciled_amount = self.cr.fetchall()
+                        partners_amount[partner_info[0]] += unreconciled_amount[0][0]
+                else:
+                    partners_amount[partner_info[0]] += partner_info[1]
+            history.append(partners_amount)
 
         for partner in partners:
             values = {}
diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml
index 6c4b701c6cf375848e38705512e184464d56e86d..a250eb9ebf7d6ac75e661970d873e04b6fad177a 100644
--- a/addons/account/views/report_invoice.xml
+++ b/addons/account/views/report_invoice.xml
@@ -5,7 +5,7 @@
     <t t-call="report.external_layout">
         <div class="page">
             <div class="row">
-                <div class="col-xs-4 col-xs-offset-8">
+                <div class="col-xs-5 col-xs-offset-7">
                     <address t-field="o.partner_id"
                         t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
                     <span t-field="o.partner_id.vat"/>
diff --git a/addons/account/views/report_overdue.xml b/addons/account/views/report_overdue.xml
index bc522aa8b9d985a8c84a9445b7ec1a99851b2541..df3934ff0deb20687d3db2a82e655aae5ab2a4e7 100644
--- a/addons/account/views/report_overdue.xml
+++ b/addons/account/views/report_overdue.xml
@@ -5,7 +5,7 @@
     <t t-call="report.external_layout">
         <div class="page">
             <div class="row">
-                <div class="col-xs-4 col-xs-offset-6">
+                <div class="col-xs-5 col-xs-offset-7">
                     <span t-field="o.name"/><br/>
                     <span t-raw="addresses[o.id].replace('\n\n', '\n').replace('\n', '&lt;br&gt;')"/>
                      <span t-field="o.vat"/>
diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py
index 8d470f45637c4a5153082fb03defd3f1e2783fd0..4b2352bc880d6e78dae42902e73df28cca8dfa42 100644
--- a/addons/account_analytic_analysis/account_analytic_analysis.py
+++ b/addons/account_analytic_analysis/account_analytic_analysis.py
@@ -69,7 +69,7 @@ class account_analytic_invoice_line(osv.osv):
         if partner_id:
             part = self.pool.get('res.partner').browse(cr, uid, partner_id, context=local_context)
             if part.lang:
-                context.update({'lang': part.lang})
+                local_context.update({'lang': part.lang})
 
         result = {}
         res = self.pool.get('product.product').browse(cr, uid, product, context=local_context)
@@ -79,7 +79,12 @@ class account_analytic_invoice_line(osv.osv):
             price = res.price
         else:
             price = res.list_price
-        result.update({'name': name or res.description or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price})
+        if not name:
+            name = self.pool.get('product.product').name_get(cr, uid, [res.id], context=local_context)[0][1]
+            if res.description_sale:
+                name += '\n'+res.description_sale
+
+        result.update({'name': name or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price})
 
         res_final = {'value':result}
         if result['uom_id'] != res.uom_id.id:
diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml
index 97fb15e929097466b36723d147b15cc4ef792f57..af6eb47ffa40f0e2df3c048c2837f540e35757f4 100644
--- a/addons/account_analytic_analysis/account_analytic_analysis_view.xml
+++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml
@@ -169,7 +169,7 @@
                     <div attrs="{'invisible': [('recurring_invoices','=',False)]}">
                         <field name="recurring_invoice_line_ids">
                             <tree string="Account Analytic Lines" editable="bottom">
-                                <field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, name, parent.partner_id, price_unit, parent.pricelist_id, parent.company_id)"/>
+                                <field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, False, parent.partner_id, False, parent.pricelist_id, parent.company_id)"/>
                                 <field name="name"/>
                                 <field name="quantity"/>
                                 <field name="uom_id"/>
diff --git a/addons/account_budget/account_budget.py b/addons/account_budget/account_budget.py
index 753a5df79f4642308c0f71388090edd51ed4e993..78e85716bbdc3069a210092fc153ce80d617a403 100644
--- a/addons/account_budget/account_budget.py
+++ b/addons/account_budget/account_budget.py
@@ -22,6 +22,7 @@
 import datetime
 
 from openerp.osv import fields, osv
+from openerp.tools import ustr
 from openerp.tools.translate import _
 
 import openerp.addons.decimal_precision as dp
@@ -114,7 +115,7 @@ class crossovered_budget_lines(osv.osv):
         for line in self.browse(cr, uid, ids, context=context):
             acc_ids = [x.id for x in line.general_budget_id.account_ids]
             if not acc_ids:
-                raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % str(line.general_budget_id.name))
+                raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % ustr(line.general_budget_id.name))
             date_to = line.date_to
             date_from = line.date_from
             if context.has_key('wizard_date_from'):
diff --git a/addons/account_followup/views/report_followup.xml b/addons/account_followup/views/report_followup.xml
index 6c79fe4cc554987db045d987c516202c5ca2bc08..c0d98e7bb28c6f043784bf96a8a412f1e4adda3c 100644
--- a/addons/account_followup/views/report_followup.xml
+++ b/addons/account_followup/views/report_followup.xml
@@ -7,7 +7,7 @@
             <t t-call="report.external_layout">
                 <div class="page">
                     <div class="row">
-                        <div class="col-xs-4 col-xs-offset-6">
+                        <div class="col-xs-5 col-xs-offset-7">
                             <div t-field="o.partner_id" 
                                 t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
                              <span t-field="o.partner_id.vat"/>
diff --git a/addons/base_gengo/doc/changelog.rst b/addons/base_gengo/doc/changelog.rst
index fe343069a381e2af1d03512652ceccd9d5899f4b..19f93bfa5a87b144fcdcb5c346bb1690551fa05f 100644
--- a/addons/base_gengo/doc/changelog.rst
+++ b/addons/base_gengo/doc/changelog.rst
@@ -3,7 +3,7 @@
 ========================
 
 ******
-saas-5
+saas-4
 ******
 
-  - Library update: ``mygengo`` (https://pypi.python.org/pypi/mygengo/1.3.3) was outdated and has been replaced by ``gengo`` (https://pypi.python.org/pypi/gengo).
+- Library update: ``mygengo`` (https://pypi.python.org/pypi/mygengo/1.3.3) was outdated and has been replaced by ``gengo`` (https://pypi.python.org/pypi/gengo).
diff --git a/addons/crm_partner_assign/security/ir.model.access.csv b/addons/crm_partner_assign/security/ir.model.access.csv
index 6a26c574a1c7b5d8d69fc2222549f44f31d985d1..d5324ba6c53c62477c1acea9d0e60f42e9cf7d88 100644
--- a/addons/crm_partner_assign/security/ir.model.access.csv
+++ b/addons/crm_partner_assign/security/ir.model.access.csv
@@ -3,6 +3,7 @@ access_ crm_lead_report_assign,crm.lead.report.assign,model_crm_lead_report_assi
 access_ crm_lead_report_assign_all,crm.lead.report.assign.all,model_crm_lead_report_assign,base.group_user,1,0,0,0
 access_crm_partner_report,crm.partner.report.assign.all,model_crm_partner_report_assign,base.group_sale_salesman,1,0,0,0
 access_res_partner_grade,res.partner.grade,model_res_partner_grade,base.group_sale_salesman,1,1,1,0
+access_res_partner_grade_public,res.partner.grade,model_res_partner_grade,base.group_public,1,0,0,0
 access_res_partner_grade_manager,res.partner.grade.manager,model_res_partner_grade,base.group_sale_manager,1,1,1,1
 "access_partner_activation_manager","res.partner.activation.manager","model_res_partner_activation","base.group_partner_manager",1,1,1,1
-partner_access_crm_lead,crm.lead,model_crm_lead,base.group_portal,1,1,0,0
\ No newline at end of file
+partner_access_crm_lead,crm.lead,model_crm_lead,base.group_portal,1,1,0,0
diff --git a/addons/delivery/delivery.py b/addons/delivery/delivery.py
index 46d76180d08d37e492c5214c925a06e7814b1c13..873b7e60662e4b0d2915b83db60718a048f8cf64 100644
--- a/addons/delivery/delivery.py
+++ b/addons/delivery/delivery.py
@@ -192,15 +192,16 @@ class delivery_grid(osv.osv):
         weight = 0
         volume = 0
         quantity = 0
+        product_uom_obj = self.pool.get('product.uom')
         for line in order.order_line:
             if not line.product_id or line.is_delivery:
                 continue
-            weight += (line.product_id.weight or 0.0) * line.product_uom_qty
-            volume += (line.product_id.volume or 0.0) * line.product_uom_qty
-            quantity += line.product_uom_qty
+            q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uos_qty, line.product_id.uom_id.id)
+            weight += (line.product_id.weight or 0.0) * q
+            volume += (line.product_id.volume or 0.0) * q
+            quantity += q
         total = order.amount_total or 0.0
 
-
         return self.get_price_from_picking(cr, uid, id, total,weight, volume, quantity, context=context)
 
     def get_price_from_picking(self, cr, uid, id, total, weight, volume, quantity, context=None):
diff --git a/addons/hr_payroll/views/report_payslip.xml b/addons/hr_payroll/views/report_payslip.xml
index 5ac9dfa557eb65a46585c8305aeadd4ff0e27bc4..b30cb089d1a165cf064b7a16ad0e57da1168ab92 100644
--- a/addons/hr_payroll/views/report_payslip.xml
+++ b/addons/hr_payroll/views/report_payslip.xml
@@ -19,7 +19,7 @@
                         <tr>
                             <td><strong>Address</strong></td>
                             <td colspan="3">
-                                <div t-filed="o.employee_id.address_home_id"
+                                <div t-field="o.employee_id.address_home_id"
                                     t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
                             </td>
                         </tr>
diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py
index 9c69f5db94bcdfb2234e323a7f6cc92b491e10cd..775b84756ce63b82a3944b81fd77b8d613924f07 100644
--- a/addons/hr_recruitment/hr_recruitment.py
+++ b/addons/hr_recruitment/hr_recruitment.py
@@ -114,6 +114,15 @@ class hr_applicant(osv.Model):
                 return int(department_ids[0][0])
         return None
 
+    def _get_default_company_id(self, cr, uid, department_id=None, context=None):
+        company_id = False
+        if department_id:
+            department = self.pool['hr.department'].browse(cr,  uid, department_id, context=context)
+            company_id = department.company_id.id if department and department.company_id else False
+        if not company_id:
+            company_id = self.pool['res.company']._company_default_get(cr, uid, 'hr.applicant', context=context)
+        return company_id            
+
     def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
         access_rights_uid = access_rights_uid or uid
         stage_obj = self.pool.get('hr.recruitment.stage')
@@ -231,7 +240,7 @@ class hr_applicant(osv.Model):
         'user_id': lambda s, cr, uid, c: uid,
         'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
         'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c),
-        'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'hr.applicant', context=c),
+        'company_id': lambda s, cr, uid, c: s._get_default_company_id(cr, uid, s._get_default_department_id(cr, uid, c), c),
         'color': 0,
         'date_last_stage_update': fields.datetime.now,
     }
diff --git a/addons/lunch/views/report_lunchorder.xml b/addons/lunch/views/report_lunchorder.xml
index 93d43f6521db58ccff3887e7a9a9de261657edfa..30401bc142be26703515f4f3fb1be603d9cea219 100644
--- a/addons/lunch/views/report_lunchorder.xml
+++ b/addons/lunch/views/report_lunchorder.xml
@@ -8,7 +8,7 @@
                     <div class="oe_structure"/>
 
                     <div class="row">
-                        <div class="col-xs-4 col-xs-offset-7">
+                        <div class="col-xs-5 col-xs-offset-7">
                             <div t-field="user.partner_id"
                                 t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
                         </div>
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index acb1793b7bdb4982f818d82b59d0e7af20647cc3..11f93e25632ac9f013155a761431702ccdd2fd96 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -669,9 +669,10 @@ class mail_thread(osv.AbstractModel):
 
     def message_get_default_recipients(self, cr, uid, ids, context=None):
         if context and context.get('thread_model') and context['thread_model'] in self.pool and context['thread_model'] != self._name:
-            sub_ctx = dict(context)
-            sub_ctx.pop('thread_model')
-            return self.pool[context['thread_model']].message_get_default_recipients(cr, uid, ids, context=sub_ctx)
+            if hasattr(self.pool[context['thread_model']], 'message_get_default_recipients'):
+                sub_ctx = dict(context)
+                sub_ctx.pop('thread_model')
+                return self.pool[context['thread_model']].message_get_default_recipients(cr, uid, ids, context=sub_ctx)
         res = {}
         for record in self.browse(cr, SUPERUSER_ID, ids, context=context):
             recipient_ids, email_to, email_cc = set(), False, False
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index 99a7751e15e9a5633406a421070d54a7f2186842..e5eca7246595c8776cf42bbea37d945353f51773 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -919,15 +919,45 @@ openerp.mail = function (session) {
             this.$('.oe_mail_expand').on('click', this.on_expand);
             this.$('.oe_mail_reduce').on('click', this.on_expand);
             this.$('.oe_mail_action_model').on('click', this.on_record_clicked);
+            this.$('.oe_mail_action_author').on('click', this.on_record_author_clicked);
         },
 
         on_record_clicked: function  (event) {
+            event.preventDefault();
+            var self = this;
             var state = {
                 'model': this.model,
                 'id': this.res_id,
                 'title': this.record_name
             };
             session.webclient.action_manager.do_push_state(state);
+            this.context.params = {
+                model: this.model,
+                res_id: this.res_id,
+            };
+            this.thread.ds_thread.call("message_redirect_action", {context: this.context}).then(function(action){
+                self.do_action(action); 
+            });
+        },
+
+        on_record_author_clicked: function  (event) {
+            event.preventDefault();
+            var partner_id = $(event.target).data('partner');
+            var state = {
+                'model': 'res.partner',
+                'id': partner_id,
+                'title': this.record_name
+            };
+            session.webclient.action_manager.do_push_state(state);
+            var action = {
+                type:'ir.actions.act_window',
+                view_type: 'form',
+                view_mode: 'form',
+                res_model: 'res.partner',
+                views: [[false, 'form']],
+                res_id: partner_id,
+            }
+            this.do_action(action);
         },
 
         /* Call the on_compose_message on the thread of this message. */
diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml
index ec7b0fa2911d01df7eba280eb9952469f11e0726..3aea4a19555638987bce512d368c145313536b88 100644
--- a/addons/mail/static/src/xml/mail.xml
+++ b/addons/mail/static/src/xml/mail.xml
@@ -273,7 +273,7 @@
                     <t t-if="widget.attachment_ids.length > 0">
                         <div class="oe_msg_attachment_list"></div>
                     </t>
-                    <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-esc="widget.author_id[2]"/></a>
+                    <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}" t-att-data-partner="widget.author_id[0]" class="oe_mail_action_author"><t t-esc="widget.author_id[2]"/></a>
                     <span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-esc="widget.author_id[2]"/></span>
                     <t t-if="widget.type == 'notification'">
                         updated document
@@ -293,7 +293,7 @@
                     <t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
                             t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
                         <span t-attf-class="oe_partner_follower">
-                        <a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-esc="partner[1]"/></a>
+                        <a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}" t-att-data-partner="partner[0]" class="oe_mail_action_author"><t t-esc="partner[1]"/></a>
                         <t t-if="!widget.options.show_link" t-esc="partner[1]"/>
                         </span>
                         <t t-if="!partner_last">,</t>
diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py
index 2e8a82a8f4d5dddb0f7e6df76a35ff556321d40e..f721ed2f3858af1dd476daa518eb3aad58055f90 100644
--- a/addons/mass_mailing/models/mass_mailing.py
+++ b/addons/mass_mailing/models/mass_mailing.py
@@ -4,10 +4,9 @@ from datetime import datetime
 from dateutil import relativedelta
 import json
 import random
-import urllib
-import urlparse
 
 from openerp import tools
+from openerp.exceptions import Warning
 from openerp.tools.safe_eval import safe_eval as eval
 from openerp.tools.translate import _
 from openerp.osv import osv, fields
@@ -62,6 +61,12 @@ class MassMailingContact(osv.Model):
         rec_id = self.create(cr, uid, {'name': name, 'email': email}, context=context)
         return self.name_get(cr, uid, [rec_id], context)[0]
 
+    def message_get_default_recipients(self, cr, uid, ids, context=None):
+        res = {}
+        for record in self.browse(cr, uid, ids, context=context):
+            res[record.id] = {'partner_ids': [], 'email_to': record.email, 'email_cc': False}
+        return res
+
 
 class MassMailingList(osv.Model):
     """Model of a contact list. """
@@ -549,6 +554,8 @@ class MassMailing(osv.Model):
         for mailing in self.browse(cr, uid, ids, context=context):
             # instantiate an email composer + send emails
             res_ids = self.get_recipients(cr, uid, mailing, context=context)
+            if not res_ids:
+                raise Warning('Please select recipients.')
             comp_ctx = dict(context, active_ids=res_ids)
             composer_values = {
                 'author_id': author_id,
diff --git a/addons/mrp_repair/views/report_mrprepairorder.xml b/addons/mrp_repair/views/report_mrprepairorder.xml
index 0ea3f22167c4cc1baf95a1218c96883117645493..2897fee1fd92fed5ddf6903c12bdc13f8524612b 100644
--- a/addons/mrp_repair/views/report_mrprepairorder.xml
+++ b/addons/mrp_repair/views/report_mrprepairorder.xml
@@ -22,7 +22,7 @@
                                 <p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
                             </div>                        
                         </div>
-                        <div class="col-xs-4 col-xs-offset-2">
+                        <div class="col-xs-5 col-xs-offset-1">
                             <div t-field="o.partner_id"
                                 t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
                         </div>
diff --git a/addons/pad/static/src/img/pad_link_companies.jpeg b/addons/pad/static/src/img/pad_link_companies.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..1bce3a5618652970429d1febfd7c613c1c330755
Binary files /dev/null and b/addons/pad/static/src/img/pad_link_companies.jpeg differ
diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml
index fc195f86ee41436baa2fe93152c530a93ccfcfd7..391c61a8e948bc57f13fcd46b12036d82c1e7cc9 100644
--- a/addons/purchase/edi/purchase_order_action_data.xml
+++ b/addons/purchase/edi/purchase_order_action_data.xml
@@ -111,7 +111,7 @@
     <p style="border-left: 1px solid #8e0000; margin-left: 30px;">
        &nbsp;&nbsp;<strong>REFERENCES</strong><br />
        &nbsp;&nbsp;Order number: <strong>${object.name}</strong><br />
-       &nbsp;&nbsp;Order total: <strong>${object.amount_total} ${object.pricelist_id.currency_id.name}</strong><br />
+       &nbsp;&nbsp;Order total: <strong>${object.amount_total} ${object.currency_id.name}</strong><br />
        &nbsp;&nbsp;Order date: ${object.date_order}<br />
        % if object.origin:
        &nbsp;&nbsp;Order reference: ${object.origin}<br />
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 6ff6feae376ac751345033f24d92639330bc0ed7..67b07644dc4b2d06103d1a496c859c55eadf7fb1 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -220,7 +220,7 @@ class purchase_order(osv.osv):
         'picking_ids': fields.function(_get_picking_ids, method=True, type='one2many', relation='stock.picking', string='Picking List', help="This is the list of reception operations that have been generated for this purchase order."),
         'shipped':fields.boolean('Received', readonly=True, select=True, help="It indicates that a picking has been done"),
         'shipped_rate': fields.function(_shipped_rate, string='Received Ratio', type='float'),
-        'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been paid"),
+        'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been validated"),
         'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', type='float'),
         'invoice_method': fields.selection([('manual','Based on Purchase Order lines'),('order','Based on generated draft invoice'),('picking','Based on incoming shipments')], 'Invoicing Control', required=True,
             readonly=True, states={'draft':[('readonly',False)], 'sent':[('readonly',False)]},
diff --git a/addons/purchase/views/report_purchaseorder.xml b/addons/purchase/views/report_purchaseorder.xml
index 300149e4f1d71e6fc158a7294d671c3e3b116531..91486c035aa67b8499347c0bebbd382204d436c3 100644
--- a/addons/purchase/views/report_purchaseorder.xml
+++ b/addons/purchase/views/report_purchaseorder.xml
@@ -23,7 +23,7 @@
                                 <p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
                             </div>
                         </div>
-                        <div class="col-xs-4 col-xs-offset-2">
+                        <div class="col-xs-5 col-xs-offset-1">
                             <div t-field="o.partner_id" 
                                 t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
                         </div>
diff --git a/addons/purchase/views/report_purchasequotation.xml b/addons/purchase/views/report_purchasequotation.xml
index a18619f99f9397a7f7333d440f5768b74864dc0a..6abd64b2f334dafb292015f17f76d4bff5d51cfb 100644
--- a/addons/purchase/views/report_purchasequotation.xml
+++ b/addons/purchase/views/report_purchasequotation.xml
@@ -23,7 +23,7 @@
                                 <p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
                             </div>
                         </div>
-                        <div class="col-xs-4 col-xs-offset-2">
+                        <div class="col-xs-5 col-xs-offset-1">
                             <div t-field="o.partner_id" 
                                 t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
                         </div>
diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py
index de3bbd63db69ca0d553c1014ee6912a6c939aab1..c6bc13d38f8e64e4df7e9105de5f6f75c6b35417 100644
--- a/addons/report/controllers/main.py
+++ b/addons/report/controllers/main.py
@@ -66,7 +66,7 @@ class ReportController(Controller):
     # Misc. route utils
     #------------------------------------------------------
     @route(['/report/barcode', '/report/barcode/<type>/<path:value>'], type='http', auth="user")
-    def report_barcode(self, type, value, width=300, height=50):
+    def report_barcode(self, type, value, width=600, height=100):
         """Contoller able to render barcode images thanks to reportlab.
         Samples: 
             <img t-att-src="'/report/barcode/QR/%s' % o.name"/>
diff --git a/addons/report/data/report_paperformat.xml b/addons/report/data/report_paperformat.xml
index 275d65edd13f265b9624fa3766e9357efe6691da..f05e0afb6f077aca3837e989465caadc71dede43 100644
--- a/addons/report/data/report_paperformat.xml
+++ b/addons/report/data/report_paperformat.xml
@@ -9,7 +9,7 @@
             <field name="page_width">0</field>
             <field name="orientation">Portrait</field>
             <field name="margin_top">40</field>
-            <field name="margin_bottom">20</field>
+            <field name="margin_bottom">23</field>
             <field name="margin_left">7</field>
             <field name="margin_right">7</field>
             <field name="header_line" eval="False" />
diff --git a/addons/report/models/report.py b/addons/report/models/report.py
index d8a51387cb7055c7accc0623006b478c3989d843..cbbee7fcebda842974721739b314f6440250ff0b 100644
--- a/addons/report/models/report.py
+++ b/addons/report/models/report.py
@@ -25,10 +25,8 @@ from openerp.tools.translate import _
 from openerp.addons.web.http import request
 from openerp.tools.safe_eval import safe_eval as eval
 
-import os
+import re
 import time
-import psutil
-import signal
 import base64
 import logging
 import tempfile
@@ -52,15 +50,19 @@ try:
         ['wkhtmltopdf', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE
     )
 except OSError:
-    _logger.error('You need wkhtmltopdf to print a pdf version of the reports.')
+    _logger.info('You need wkhtmltopdf to print a pdf version of the reports.')
 else:
     out, err = process.communicate()
-    version = out.splitlines()[1].strip()
-    version = version.split(' ')[1]
+    version = re.search('([0-9.]+)', out).group(0)
     if LooseVersion(version) < LooseVersion('0.12.0'):
-        _logger.warning('Upgrade wkhtmltopdf to (at least) 0.12.0')
+        _logger.info('Upgrade wkhtmltopdf to (at least) 0.12.0')
         wkhtmltopdf_state = 'upgrade'
-    wkhtmltopdf_state = 'ok'
+    else:
+        wkhtmltopdf_state = 'ok'
+
+    if config['workers'] == 1:
+        _logger.info('You need to start OpenERP with at least two workers to print a pdf version of the reports.')
+        wkhtmltopdf_state = 'workers'
 
 
 class Report(osv.Model):
@@ -343,19 +345,20 @@ class Report(osv.Model):
         command_args = []
         tmp_dir = tempfile.gettempdir()
 
-        # Passing the cookie to wkhtmltopdf in order to resolve URL.
+        # Passing the cookie to wkhtmltopdf in order to resolve internal links.
         try:
             if request:
                 command_args.extend(['--cookie', 'session_id', request.session.sid])
         except AttributeError:
             pass
 
-        # Display arguments
+        # Wkhtmltopdf arguments
+        command_args.extend(['--quiet'])  # Less verbose error messages
         if paperformat:
+            # Convert the paperformat record into arguments
             command_args.extend(self._build_wkhtmltopdf_args(paperformat, spec_paperformat_args))
 
-        command_args.extend(['--load-error-handling', 'ignore'])
-
+        # Force the landscape orientation if necessary
         if landscape and '--orientation' in command_args:
             command_args_copy = list(command_args)
             for index, elem in enumerate(command_args_copy):
@@ -366,61 +369,46 @@ class Report(osv.Model):
         elif landscape and not '--orientation' in command_args:
             command_args.extend(['--orientation', 'landscape'])
 
+        # Execute WKhtmltopdf
         pdfdocuments = []
-        # HTML to PDF thanks to WKhtmltopdf
         for index, reporthtml in enumerate(bodies):
-            command_arg_local = []
-            pdfreport = tempfile.NamedTemporaryFile(suffix='.pdf', prefix='report.tmp.',
-                                                    mode='w+b')
-            # Directly load the document if we have it
+            local_command_args = []
+            pdfreport = tempfile.NamedTemporaryFile(suffix='.pdf', prefix='report.tmp.', mode='w+b')
+
+            # Directly load the document if we already have it
             if save_in_attachment and save_in_attachment['loaded_documents'].get(reporthtml[0]):
                 pdfreport.write(save_in_attachment['loaded_documents'].get(reporthtml[0]))
                 pdfreport.seek(0)
                 pdfdocuments.append(pdfreport)
                 continue
 
-            # Header stuff
+            # Wkhtmltopdf handles header/footer as separate pages. Create them if necessary.
             if headers:
-                head_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.header.tmp.',
-                                                        dir=tmp_dir, mode='w+')
+                head_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.header.tmp.', dir=tmp_dir, mode='w+')
                 head_file.write(headers[index])
                 head_file.seek(0)
-                command_arg_local.extend(['--header-html', head_file.name])
-
-            # Footer stuff
+                local_command_args.extend(['--header-html', head_file.name])
             if footers:
-                foot_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.footer.tmp.',
-                                                        dir=tmp_dir, mode='w+')
+                foot_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.footer.tmp.', dir=tmp_dir, mode='w+')
                 foot_file.write(footers[index])
                 foot_file.seek(0)
-                command_arg_local.extend(['--footer-html', foot_file.name])
+                local_command_args.extend(['--footer-html', foot_file.name])
 
             # Body stuff
-            content_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.body.tmp.',
-                                                       dir=tmp_dir, mode='w+')
+            content_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.body.tmp.', dir=tmp_dir, mode='w+')
             content_file.write(reporthtml[1])
             content_file.seek(0)
 
             try:
-                # If the server is running with only one worker, ask to create a secund to be able
-                # to serve the http request of wkhtmltopdf subprocess.
-                if config['workers'] == 1:
-                    ppid = psutil.Process(os.getpid()).ppid
-                    os.kill(ppid, signal.SIGTTIN)
-
-                wkhtmltopdf = command + command_args + command_arg_local
+                wkhtmltopdf = command + command_args + local_command_args
                 wkhtmltopdf += [content_file.name] + [pdfreport.name]
 
-                process = subprocess.Popen(wkhtmltopdf, stdout=subprocess.PIPE,
-                                           stderr=subprocess.PIPE)
+                process = subprocess.Popen(wkhtmltopdf, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                 out, err = process.communicate()
 
-                if config['workers'] == 1:
-                    os.kill(ppid, signal.SIGTTOU)
-
-                if process.returncode != 0:
+                if process.returncode not in [0, 1]:
                     raise osv.except_osv(_('Report (PDF)'),
-                                         _('wkhtmltopdf failed with error code = %s. '
+                                         _('Wkhtmltopdf failed (error code: %s). '
                                            'Message: %s') % (str(process.returncode), err))
 
                 # Save the pdf in attachment if marked
@@ -446,7 +434,7 @@ class Report(osv.Model):
             except:
                 raise
 
-        # Get and return the full pdf
+        # Return the entire document
         if len(pdfdocuments) == 1:
             content = pdfdocuments[0].read()
             pdfdocuments[0].close()
diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js
index 37a0fae6ea6938e1ef14e6e9b3ff61bc6f005d2c..cb0f3921482191e757b6f74acde31ecd9076574c 100644
--- a/addons/report/static/src/js/qwebactionmanager.js
+++ b/addons/report/static/src/js/qwebactionmanager.js
@@ -54,33 +54,35 @@ openerp.report = function(instance) {
                 if (action.report_type == 'qweb-html') {
                     window.open(report_url, '_blank', 'height=900,width=1280');
                     instance.web.unblockUI();
-                } else {
+                } else if (action.report_type === 'qweb-pdf') {
                     // Trigger the download of the pdf/controller report
-
-                    if (action.report_type == 'qweb-pdf') {
-                        (wkhtmltopdf_state = wkhtmltopdf_state || openerp.session.rpc('/report/check_wkhtmltopdf')).then(function (presence) {
-                            // Fallback of qweb-pdf if wkhtmltopdf is not installed
-                            if (presence == 'install' && action.report_type == 'qweb-pdf') {
-                                self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \
-    system. The report will be shown in html.<br><br><a href="http://wkhtmltopdf.org/" target="_blank">\
-    wkhtmltopdf.org</a>'), true);
-                                report_url = report_url.substring(12)
-                                window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024');
-                                instance.web.unblockUI();
-                                return;
-                            } else {
-                                if (presence == 'upgrade') {
-                                    self.do_notify(_t('Report'), _t('You should upgrade your version of\
-     Wkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as\
-     support for table-breaking between pages.<br><br><a href="http://wkhtmltopdf.org/" \
-     target="_blank">wkhtmltopdf.org</a>'), true);
-                                }
-                            }
-                            return trigger_download(self.session, response, c);
-                        });
-                    } else if (action.report_type == 'controller') {
+                    (wkhtmltopdf_state = wkhtmltopdf_state || openerp.session.rpc('/report/check_wkhtmltopdf')).then(function (presence) {
+                        // Fallback on html if wkhtmltopdf is not installed or if OpenERP is started with one worker
+                        if (presence === 'install') {
+                            self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \
+system. The report will be shown in html.<br><br><a href="http://wkhtmltopdf.org/" target="_blank">\
+wkhtmltopdf.org</a>'), true);
+                            report_url = report_url.substring(12)
+                            window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024');
+                            instance.web.unblockUI();
+                            return;
+                        } else if (presence === 'workers') {
+                            self.do_notify(_t('Report'), _t('You need to start OpenERP with at least two \
+workers to print a pdf version of the reports.'), true);
+                            report_url = report_url.substring(12)
+                            window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024');
+                            instance.web.unblockUI();
+                            return;
+                        } else if (presence === 'upgrade') {
+                            self.do_notify(_t('Report'), _t('You should upgrade your version of\
+ Wkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as\
+ support for table-breaking between pages.<br><br><a href="http://wkhtmltopdf.org/" \
+ target="_blank">wkhtmltopdf.org</a>'), true);
+                        }
                         return trigger_download(self.session, response, c);
-                    }
+                    });
+                } else if (action.report_type === 'controller') {
+                    return trigger_download(self.session, response, c);
                 }                     
             } else {
                 return self._super(action, options);
diff --git a/addons/report/views/layouts.xml b/addons/report/views/layouts.xml
index dd7a404196ec8d70766762fb0814c7de453246fc..f9c0ea7ef73017dbf0cf6f1dfd1e3dab4703283e 100644
--- a/addons/report/views/layouts.xml
+++ b/addons/report/views/layouts.xml
@@ -9,7 +9,8 @@
           t-att-data-main-object="repr(main_object) if editable else None"
           t-att-data-report-margin-top="data_report_margin_top if data_report_margin_top else None"
           t-att-data-report-header-spacing="data_report_header_spacing if data_report_header_spacing else None"
-          t-att-data-report-dpi="data_report_dpi if data_report_dpi else None">
+          t-att-data-report-dpi="data_report_dpi if data_report_dpi else None"
+          t-att-data-oe-company-name="res_company.name">
         <head>
             <meta name="viewport" content="width=device-width, initial-scale=1"/>
 
@@ -19,7 +20,6 @@
             <t t-if="not title and main_object and 'name' in main_object">
                 <t t-set="additional_title" t-value="main_object.name"/>
             </t>
-            <meta name="openerp.company" t-att-value="res_company.name"/>
             <meta name="description" t-att-value="main_object and 'website_meta_description' in main_object
                 and main_object.website_meta_description or website_meta_description"/>
             <meta name="keywords" t-att-value="main_object and 'website_meta_keywords' in main_object
diff --git a/addons/report_intrastat/views/report_intrastatinvoice.xml b/addons/report_intrastat/views/report_intrastatinvoice.xml
index c534f808c95ba26232a467f3ba9d534702470390..abf4bdd56baf1b5a2fb952727223031d3a324427 100644
--- a/addons/report_intrastat/views/report_intrastatinvoice.xml
+++ b/addons/report_intrastat/views/report_intrastatinvoice.xml
@@ -5,7 +5,7 @@
     <t t-call="report.external_layout">
         <div class="page">
             <div class="row">
-                <div class="col-xs-4 col-xs-offset-8">
+                <div class="col-xs-5 col-xs-offset-7">
                     <address t-field="o.partner_id"
                         t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
                     <span t-field="o.partner_id.vat"/>
diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py
index 60fb536ca961c3275bc9062fe5f06838d7a3c0ad..c442ea32549ae210a0b06ef5167a161e027e7862 100644
--- a/addons/report_webkit/webkit_report.py
+++ b/addons/report_webkit/webkit_report.py
@@ -156,8 +156,8 @@ class WebKitParser(report_sxw):
         """Call webkit in order to generate pdf"""
         if not webkit_header:
             webkit_header = report_xml.webkit_header
-        tmp_dir = tempfile.gettempdir()
-        out_filename = tempfile.mktemp(suffix=".pdf", prefix="webkit.tmp.")
+        fd, out_filename = tempfile.mkstemp(suffix=".pdf",
+                                            prefix="webkit.tmp.")
         file_to_del = [out_filename]
         if comm_path:
             command = [comm_path]
@@ -168,25 +168,15 @@ class WebKitParser(report_sxw):
         # default to UTF-8 encoding.  Use <meta charset="latin-1"> to override.
         command.extend(['--encoding', 'utf-8'])
         if header :
-            head_file = file( os.path.join(
-                                  tmp_dir,
-                                  str(time.time()) + '.head.html'
-                                 ),
-                                'w'
-                            )
-            head_file.write(self._sanitize_html(header.encode('utf-8')))
-            head_file.close()
+            with tempfile.NamedTemporaryFile(suffix=".head.html",
+                                             delete=False) as head_file:
+                head_file.write(self._sanitize_html(header.encode('utf-8')))
             file_to_del.append(head_file.name)
             command.extend(['--header-html', head_file.name])
         if footer :
-            foot_file = file(  os.path.join(
-                                  tmp_dir,
-                                  str(time.time()) + '.foot.html'
-                                 ),
-                                'w'
-                            )
-            foot_file.write(self._sanitize_html(footer.encode('utf-8')))
-            foot_file.close()
+            with tempfile.NamedTemporaryFile(suffix=".foot.html",
+                                             delete=False) as foot_file:
+                foot_file.write(self._sanitize_html(footer.encode('utf-8')))
             file_to_del.append(foot_file.name)
             command.extend(['--footer-html', foot_file.name])
 
@@ -204,10 +194,10 @@ class WebKitParser(report_sxw):
             command.extend(['--page-size', str(webkit_header.format).replace(',', '.')])
         count = 0
         for html in html_list :
-            html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w')
-            count += 1
-            html_file.write(self._sanitize_html(html.encode('utf-8')))
-            html_file.close()
+            with tempfile.NamedTemporaryFile(suffix="%d.body.html" %count,
+                                             delete=False) as html_file:
+                count += 1
+                html_file.write(self._sanitize_html(html.encode('utf-8')))
             file_to_del.append(html_file.name)
             command.append(html_file.name)
         command.append(out_filename)
@@ -227,9 +217,9 @@ class WebKitParser(report_sxw):
             if status :
                 raise except_osv(_('Webkit error' ),
                                  _("The command 'wkhtmltopdf' failed with error code = %s. Message: %s") % (status, error_message))
-            pdf_file = open(out_filename, 'rb')
-            pdf = pdf_file.read()
-            pdf_file.close()
+            with open(out_filename, 'rb') as pdf_file:
+                pdf = pdf_file.read()
+            os.close(fd)
         finally:
             if stderr_fd is not None:
                 os.close(stderr_fd)
diff --git a/addons/sale/views/report_saleorder.xml b/addons/sale/views/report_saleorder.xml
index c23e680e664a66b8d944de954cd9fe3af79ad86c..5c198c635a3bbd23b87f93aae96af5ad743318b8 100644
--- a/addons/sale/views/report_saleorder.xml
+++ b/addons/sale/views/report_saleorder.xml
@@ -19,7 +19,7 @@
                         <p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
                     </div>                        
                 </div>
-                <div class="col-xs-4 col-xs-offset-2">
+                <div class="col-xs-5 col-xs-offset-1">
                     <div t-field="o.partner_id"
                         t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
                 </div>
diff --git a/addons/survey/security/ir.model.access.csv b/addons/survey/security/ir.model.access.csv
index 89c001ce44ecba98ac54212b3a945ead822b77a3..e49c976ea1f4c65806ab67784a54a04113c32bb1 100644
--- a/addons/survey/security/ir.model.access.csv
+++ b/addons/survey/security/ir.model.access.csv
@@ -1,11 +1,11 @@
 id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_survey_public,survey.survey public,model_survey_survey,base.group_public,1,0,0,0
-access_survey_page_public,survey.page public,model_survey_page,base.group_public,1,0,0,0
-access_survey_question_public,survey.question public,model_survey_question,base.group_public,1,0,0,0
-access_survey_label_public,survey.label public,model_survey_label,base.group_public,1,0,0,0
-access_survey_user_input_public,survey.user_input public,model_survey_user_input,base.group_public,1,1,1,0
-access_survey_user_input_line_public,survey.user_input_line public,model_survey_user_input_line,base.group_public,1,1,1,0
-access_survey_stage_public,survey.stage public,model_survey_stage,base.group_public,1,0,0,0
+access_survey_public,survey.survey public,model_survey_survey,,1,0,0,0
+access_survey_page_public,survey.page public,model_survey_page,,1,0,0,0
+access_survey_question_public,survey.question public,model_survey_question,,1,0,0,0
+access_survey_label_public,survey.label public,model_survey_label,,1,0,0,0
+access_survey_user_input_public,survey.user_input public,model_survey_user_input,,1,1,1,0
+access_survey_user_input_line_public,survey.user_input_line public,model_survey_user_input_line,,1,1,1,0
+access_survey_stage_public,survey.stage public,model_survey_stage,,1,0,0,0
 access_survey_user,survey.survey user,model_survey_survey,base.group_survey_user,1,0,0,0
 access_survey_page_user,survey.page user,model_survey_page,base.group_survey_user,1,0,0,0
 access_survey_question_user,survey.question user,model_survey_question,base.group_survey_user,1,0,0,0
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index ffe9d26824019d6cb37face884efa7c2cd5b3216..a4ecc4e17d903416291e6b8e553e826648966415 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -2596,6 +2596,7 @@ instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(insta
         this.$('.select_records').on('click', self.on_click);
     },
     on_click: function(ev) {
+        event.preventDefault();
         var self = this;
         var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
         this.pop = new instance.web.form.SelectCreatePopup(this);
@@ -2614,15 +2615,14 @@ instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(insta
                 });
             }
             else {
-                var domain = ["id", "in", element_ids];
+                var domain = [["id", "in", element_ids]];
                 var domain_done = $.Deferred().resolve(domain);
             }
             $.when(domain_done).then(function (domain) {
                 var domain = self.pop.dataset.domain.concat(domain || []);
-                self.set_value(JSON.stringify(domain))
+                self.set_value(domain);
             });
         });
-        event.preventDefault();
     },
 });
 
@@ -4463,7 +4463,11 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
             else
                 return $.when();
         }).done(function () {
-            if (!self.o2m.options.reload_on_button) {
+            var ds = self.o2m.dataset;
+            var cached_records = _.any([ds.to_create, ds.to_delete, ds.to_write], function(value) {
+                return value.length;
+            });
+            if (!self.o2m.options.reload_on_button && !cached_records) {
                 self.handle_button(name, id, callback);
             }else {
                 self.handle_button(name, id, function(){
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 753d52d497a473ed4b71765268ee1bff1442737a..c6e28301c42b5d9e4022c2ccb204b999609f912f 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -436,6 +436,16 @@ instance.web.ActionManager = instance.web.Widget.extend({
     ir_actions_act_window: function (action, options) {
         var self = this;
 
+        if (action.target === 'current'){
+            action.context['active_model'] = action.res_model;
+            if (action.res_id){
+                action.context['active_id'] = action.res_id;
+                action.context['active_ids'] = [action.res_id];
+            } else{
+                delete action.context['active_id'];
+                delete action.context['active_ids'];
+            }
+        }
         return this.ir_actions_common({
             widget: function () { return new instance.web.ViewManagerAction(self, action); },
             action: action,
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index 39f3067720f5dcdc6125a29cb6f27f4874c56a82..446080875a6b8c0439f8c4825433eab83afdf18d 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -378,7 +378,7 @@ class Website(openerp.addons.web.controllers.main.Home):
         """
         response = werkzeug.wrappers.Response()
         return request.registry['website']._image(
-                    request.cr, request.uid, model, id, field, response)
+                    request.cr, request.uid, model, id, field, response, max_width, max_height)
 
 
     #------------------------------------------------------
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 360b34c877c5ff74a2548d64783dc995a51b1f36..44b3f771f62f20000ba265199dd24972c6841125 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -141,49 +141,50 @@ class ir_http(orm.AbstractModel):
             return response
 
     def _handle_exception(self, exception=None, code=500):
-        if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response:
-            return exception.response
-
-        attach = self._serve_attachment()
-        if attach:
-            return attach
-
-        if getattr(request, 'website_enabled', False) and request.website:
-            values = dict(
-                exception=exception,
-                traceback=traceback.format_exc(exception),
-            )
-            if exception:
-                code = getattr(exception, 'code', code)
-                if isinstance(exception, ir_qweb.QWebException):
-                    values.update(qweb_exception=exception)
-                    if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
-                        code = 403
-            if code == 500:
-                logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
-                if 'qweb_exception' in values:
-                    view = request.registry.get("ir.ui.view")
-                    views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
-                    to_reset = [v for v in views if v.model_data_id.noupdate is True]
-                    values['views'] = to_reset
-            elif code == 403:
-                logger.warn("403 Forbidden:\n\n%s", values['traceback'])
-
-            values.update(
-                status_message=werkzeug.http.HTTP_STATUS_CODES[code],
-                status_code=code,
-            )
-
-            if not request.uid:
-                self._auth_method_public()
-
-            try:
-                html = request.website._render('website.%s' % code, values)
-            except Exception:
-                html = request.website._render('website.http_error', values)
-            return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
+        try:
+            return super(ir_http, self)._handle_exception(exception)
+        except Exception:
 
-        return super(ir_http, self)._handle_exception(exception)
+            attach = self._serve_attachment()
+            if attach:
+                return attach
+
+            if getattr(request, 'website_enabled', False) and request.website:
+                values = dict(
+                    exception=exception,
+                    traceback=traceback.format_exc(exception),
+                )
+                if exception:
+                    code = getattr(exception, 'code', code)
+                    if isinstance(exception, ir_qweb.QWebException):
+                        values.update(qweb_exception=exception)
+                        if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
+                            code = 403
+                if code == 500:
+                    logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
+                    if 'qweb_exception' in values:
+                        view = request.registry.get("ir.ui.view")
+                        views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
+                        to_reset = [v for v in views if v.model_data_id.noupdate is True]
+                        values['views'] = to_reset
+                elif code == 403:
+                    logger.warn("403 Forbidden:\n\n%s", values['traceback'])
+
+                values.update(
+                    status_message=werkzeug.http.HTTP_STATUS_CODES[code],
+                    status_code=code,
+                )
+
+                if not request.uid:
+                    self._auth_method_public()
+
+                try:
+                    html = request.website._render('website.%s' % code, values)
+                except Exception:
+                    html = request.website._render('website.http_error', values)
+                return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
+
+            raise
 
 class ModelConverter(ir.ir_http.ModelConverter):
     def __init__(self, url_map, model=False, domain='[]'):
diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py
index ad2b63a6dd9868d58b71dc393f71a25154f5c024..0e1fe2beb89c74127a0db505ae41fcab46ccc4cd 100644
--- a/addons/website/models/ir_qweb.py
+++ b/addons/website/models/ir_qweb.py
@@ -15,6 +15,7 @@ import urllib2
 import urlparse
 import re
 
+import werkzeug.urls
 import werkzeug.utils
 from dateutil import parser
 from lxml import etree, html
@@ -265,10 +266,19 @@ class Image(orm.AbstractModel):
         if options is None: options = {}
         classes = ['img', 'img-responsive'] + options.get('class', '').split()
 
-        return ir_qweb.HTMLSafe('<img class="%s" src="/website/image?model=%s&field=%s&id=%s"/>' % (
+        url_params = {
+            'model': record._model._name,
+            'field': field_name,
+            'id': record.id,
+        }
+        for options_key in ['max_width', 'max_height']:
+            if options.get(options_key):
+                url_params[options_key] = options[options_key]
+
+        return ir_qweb.HTMLSafe('<img class="%s" src="/website/image?%s"/>' % (
             ' '.join(itertools.imap(werkzeug.utils.escape, classes)),
-            record._model._name,
-            field_name, record.id))
+            werkzeug.urls.url_encode(url_params)
+        ))
 
     local_url_re = re.compile(r'^/(?P<module>[^]]+)/static/(?P<rest>.+)$')
     def from_html(self, cr, uid, model, column, element, context=None):
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 433d8644698cee022a9f1326a50b16368646fc89..db02dcce51e75ae9396dd244af08e25cf97f5b2b 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -541,7 +541,10 @@ class website(osv.osv):
         response.mimetype = Image.MIME[image.format]
 
         w, h = image.size
-        max_w, max_h = int(max_width), int(max_height)
+        try:
+            max_w, max_h = int(max_width), int(max_height)
+        except:
+            max_w, max_h = (maxint, maxint)
 
         if w < max_w and h < max_h:
             response.data = data
diff --git a/addons/website/static/src/js/website.seo.js b/addons/website/static/src/js/website.seo.js
index 8588b7a37655fe63959710a20325175ecf5471b7..1c4bad90ffc37a5eef24105347792891f09a98cb 100644
--- a/addons/website/static/src/js/website.seo.js
+++ b/addons/website/static/src/js/website.seo.js
@@ -264,21 +264,21 @@
         },
         description: function () {
             var $description = $('meta[name=description]');
-            return ($description.length > 0) && ($description.attr('value') && $description.attr('value').trim());
+            return ($description.length > 0) && ($description.attr('content') && $description.attr('content').trim());
         },
         changeDescription: function (description) {
             // TODO create tag if missing
-            $('meta[name=description]').attr('value', description);
+            $('meta[name=description]').attr('content', description);
             this.trigger('description-changed', description);
         },
         keywords: function () {
             var $keywords = $('meta[name=keywords]');
-            var parsed = ($keywords.length > 0) && $keywords.attr('value') && $keywords.attr('value').split(",");
+            var parsed = ($keywords.length > 0) && $keywords.attr('content') && $keywords.attr('content').split(",");
             return (parsed && parsed[0]) ? parsed: [];
         },
         changeKeywords: function (keywords) {
             // TODO create tag if missing
-            $('meta[name=keywords]').attr('value', keywords.join(","));
+            $('meta[name=keywords]').attr('content', keywords.join(","));
             this.trigger('keywords-changed', keywords);
         },
         headers: function (tag) {
@@ -296,7 +296,7 @@
             });
         },
         company: function () {
-            return $('meta[name="openerp.company"]').attr('value');
+            return $('html').attr('data-oe-company-name');
         },
         bodyText: function () {
             return $('body').children().not('.js_seo_configuration').text();
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index 6226e3a0aa7d091b9c8ed965a27fb82e2ba70ebd..56d954e8a353be38e42caadc50ff8755dfc58999 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -61,8 +61,10 @@
           t-att-data-editable="'1' if editable else None"
           t-att-data-translatable="'1' if translatable else None"
           t-att-data-view-xmlid="xmlid if editable else None"
-          t-att-data-main-object="repr(main_object) if editable else None">
+          t-att-data-main-object="repr(main_object) if editable else None"
+          t-att-data-oe-company-name="res_company.name">
         <head>
+            <meta charset="utf-8" />
             <t t-if="main_object and 'website_meta_title' in main_object">
                 <t t-set="title" t-value="main_object.website_meta_title"/>
             </t>
@@ -73,10 +75,9 @@
                 <t t-set="title"><t t-raw="res_company.name"/><t t-if="additional_title"> - <t t-raw="additional_title"/></t></t>
             </t>
             <meta name="viewport" content="initial-scale=1"/>
-            <meta name="openerp.company" t-att-value="res_company.name"/>
-            <meta name="description" t-att-value="main_object and 'website_meta_description' in main_object
+            <meta name="description" t-att-content="main_object and 'website_meta_description' in main_object
                 and main_object.website_meta_description or website_meta_description"/>
-            <meta name="keywords" t-att-value="main_object and 'website_meta_keywords' in main_object
+            <meta name="keywords" t-att-content="main_object and 'website_meta_keywords' in main_object
                 and main_object.website_meta_keywords or website_meta_keywords"/>
             <title><t t-esc="title"/></title>
 
@@ -137,14 +138,14 @@
                 <footer>
                     <div class="container hidden-print" id="footer_container">
                         <div class="row">
-                            <div class="col-md-3" name="product">
+                            <div class="col-md-3">
                                 <h4>Our products &amp; Services</h4>
                                 <ul class="list-unstyled" name="products">
                                     <li><a href="/">Home</a></li>
                                 </ul>
                             </div>
                             <div class="col-md-3" name="info">
-                                <h4 name="info_title">Connect with us</h4>
+                                <h4>Connect with us</h4>
                                 <ul class="list-unstyled">
                                     <li><a href="/page/website.contactus">Contact us</a></li>
                                 </ul>
@@ -161,7 +162,7 @@
                                     <a t-att-href="website.social_github" t-if="website.social_github"><i class="fa fa-github"/></a>
                                 </h2>
                             </div>
-                            <div class="col-md-5 col-lg-offset-1" name="about_us">
+                            <div class="col-md-5 col-lg-offset-1">
                                 <div>
                                     <h4>
                                         <span t-field="res_company.name">Your Company</span>
@@ -306,7 +307,7 @@
 
 <template id="debugger" inherit_id="website.layout" optional="disabled" name="Debugger &amp; Tests">
     <xpath expr='//t[@name="layout_head"]' position="after">
-        <script type="text/javascript" src="/website/static/src/js/website.tour.js"></script>
+        <t t-set="debugger_hook" t-value="1" />
     </xpath>
 </template>
 
diff --git a/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml b/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml
index f960511edfc35df730721aa187b9342e0881d18e..06b5317c4eecd570c56c94a52f2884b5005d59cc 100644
--- a/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml
+++ b/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml
@@ -86,8 +86,8 @@
                         </t>
                         <div class="media">
                             <a class="pull-left" t-attf-href="/partners/#{slug(partner)}?#{current_grade and 'grade_id=%s&amp;' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}"
-                               t-field="partner.image_small"
-                               t-field-options='{"widget": "image", "class": "media-object"}'
+                               t-field="partner.image"
+                               t-field-options='{"widget": "image", "class": "media-object", "max_width": 128}'
                             ></a>
                             <div class="media-body o_partner_body" style="min-height: 64px;">
                                 <a class="media-heading" t-attf-href="/partners/#{slug(partner)}?#{current_grade and 'grade_id=%s&amp;' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}">
diff --git a/addons/website_event_sale/views/website_event_sale.xml b/addons/website_event_sale/views/website_event_sale.xml
index 967d9c029ccfda9edae807187f6eb0917ecba133..cf46797b34d6dd5e4b4e50f1ab923e36d388c6cf 100644
--- a/addons/website_event_sale/views/website_event_sale.xml
+++ b/addons/website_event_sale/views/website_event_sale.xml
@@ -3,7 +3,7 @@
 <data>
 
 <template id="debugger" inherit_id="website.debugger" name="Event Debugger">
-    <xpath expr="//script[last()]" position="after">
+    <xpath expr='//t[@t-set="debugger_hook"]' position="after">
         <script type="text/javascript" src="/website_event_sale/static/src/js/website.tour.event_sale.js"></script>
     </xpath>
 </template>
diff --git a/addons/website_event_track/controllers/event.py b/addons/website_event_track/controllers/event.py
index f0a9efa8dfcc06af0a352cef1815bee7de4b9672..b2e689e5cb68118d6974fc396aec8af5480ccd2f 100644
--- a/addons/website_event_track/controllers/event.py
+++ b/addons/website_event_track/controllers/event.py
@@ -88,10 +88,21 @@ class website_event(http.Controller):
             days_tracks_count[day] = len(tracks)
             days[day] = self._prepare_calendar(event, tracks)
 
+        cr, uid, context = request.cr, request.uid, request.context
+        track_obj = request.registry['event.track']
+        tracks_ids = track_obj.search(cr, openerp.SUPERUSER_ID, [('event_id', '=', event.id)], context=context)
+        speakers = dict()
+        for t in track_obj.browse(cr, openerp.SUPERUSER_ID, tracks_ids, context=context):
+            acc = ""
+            for speaker in t.speaker_ids:
+                acc = speaker.name + u" – " + acc if acc else speaker.name
+            speakers[t.id] = acc
+
         return request.website.render("website_event_track.agenda", {
             'event': event,
             'days': days,
             'days_nbr': days_tracks_count,
+            'speakers': speakers,
             'tag': tag
         })
 
diff --git a/addons/website_event_track/views/website_event.xml b/addons/website_event_track/views/website_event.xml
index cb5140282664bfc83a435d45740dbd9b51f27a05..9aece0f5c11435633dccdd5e6122fe21b5450170 100644
--- a/addons/website_event_track/views/website_event.xml
+++ b/addons/website_event_track/views/website_event.xml
@@ -85,8 +85,8 @@
                                         <a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
                                             <span t-esc="track and track.name"/>
                                         </a>
-                                        <div class="text-muted" t-foreach="track.speaker_ids" t-as="speaker">
-                                            <small t-esc="speaker.display_name"/>
+                                        <div class="text-muted">
+                                            <small t-esc="speakers[track.id]"/>
                                         </div>
                                     </t>
                                 </td>
@@ -98,11 +98,11 @@
                     <t t-set="track" t-value="dt[1][False][0]"/>
                     <td t-att-colspan="len(locations)-1" t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''}">
                         <a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
-                            <span t-esc="track.name"/><br/>
-                            <div class="text-muted" t-foreach="track.speaker_ids" t-as="speaker">
-                                <small t-esc="speaker.display_name"/>
-                            </div>
+                            <span t-esc="track.name"/>
                         </a>
+                        <div class="text-muted">
+                            <small t-esc="speakers[track.id]"/>
+                        </div>
                     </td>
                 </t>
             </tr>
diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py
index 53397f38b63d4d4d3ba2197bee13de6b25627235..81cbfdcadc89d1c18f6cb82107780a990e4da0d9 100644
--- a/addons/website_forum/controllers/main.py
+++ b/addons/website_forum/controllers/main.py
@@ -330,13 +330,12 @@ class WebsiteForum(http.Controller):
         cr, uid, context = request.cr, request.uid, request.context
         if kwargs.get('comment') and post.forum_id.id == forum.id:
             # TDE FIXME: check that post_id is the question or one of its answers
-            if request.registry['res.users'].has_group(cr, uid, 'website_mail.group_comment'):
-                request.registry['forum.post'].message_post(
-                    cr, uid, post.id,
-                    body=kwargs.get('comment'),
-                    type='comment',
-                    subtype='mt_comment',
-                    context=dict(context, mail_create_nosubcribe=True))
+            request.registry['forum.post'].message_post(
+                cr, uid, post.id,
+                body=kwargs.get('comment'),
+                type='comment',
+                subtype='mt_comment',
+                context=dict(context, mail_create_nosubcribe=True))
         return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
 
     @http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/toggle_correct', type='json', auth="public", website=True)
diff --git a/addons/website_hr_recruitment/security/website_hr_recruitment_security.xml b/addons/website_hr_recruitment/security/website_hr_recruitment_security.xml
index 792995ca606671ea122ac1ae895a3fcda48a72d0..5d47e69feadfc597481f8da28fe09a431972e625 100644
--- a/addons/website_hr_recruitment/security/website_hr_recruitment_security.xml
+++ b/addons/website_hr_recruitment/security/website_hr_recruitment_security.xml
@@ -11,6 +11,26 @@
         <field name="perm_create" eval="False"/>
         <field name="perm_unlink" eval="False"/>
     </record>
+    <record id="hr_job_portal" model="ir.rule">
+        <field name="name">Job Positions: Portal</field>
+        <field name="model_id" ref="hr.model_hr_job"/>
+        <field name="domain_force">[('website_published', '=', True)]</field>
+        <field name="groups" eval="[(4, ref('base.group_portal'))]"/>
+        <field name="perm_read" eval="True"/>
+        <field name="perm_write" eval="False"/>
+        <field name="perm_create" eval="False"/>
+        <field name="perm_unlink" eval="False"/>
+    </record>
+    <record id="hr_job_officer" model="ir.rule">
+        <field name="name">Job Positions: HR Officer</field>
+        <field name="model_id" ref="hr.model_hr_job"/>
+        <field name="domain_force">[(1, '=', 1)]</field>
+        <field name="groups" eval="[(4, ref('base.group_hr_user'))]"/>
+        <field name="perm_read" eval="True"/>
+        <field name="perm_write" eval="False"/>
+        <field name="perm_create" eval="False"/>
+        <field name="perm_unlink" eval="False"/>
+    </record>
     <record id="hr_department_public" model="ir.rule">
         <field name="name">Job department: Public</field>
         <field name="model_id" ref="hr.model_hr_department"/>
diff --git a/addons/website_mail/controllers/main.py b/addons/website_mail/controllers/main.py
index 0932794ee288523c8aa59a1487dab20225279224..de69fba490a318b0b8a19db39e552d4a8d9a274c 100644
--- a/addons/website_mail/controllers/main.py
+++ b/addons/website_mail/controllers/main.py
@@ -62,6 +62,7 @@ class WebsiteMail(http.Controller):
 
     @http.route(['/website_mail/is_follower'], type='json', auth="public", website=True)
     def call(self, model, id, **post):
+        id = int(id)
         cr, uid, context = request.cr, request.uid, request.context
 
         partner_obj = request.registry.get('res.partner')
@@ -74,17 +75,28 @@ class WebsiteMail(http.Controller):
             partner_id = users_obj.browse(cr, SUPERUSER_ID, uid, context).partner_id
         elif request.session.get('partner_id'):
             partner_id = partner_obj.browse(cr, SUPERUSER_ID, request.session.get('partner_id'), context)
-        
-        email = ""
-        is_follower = False
-        if partner_id:
-            email = partner_id and partner_id.email
-            is_follower = partner_id.id in [
-                fol.id for fol in obj.browse(cr, SUPERUSER_ID, id, context).message_follower_ids]
+        email = partner_id and partner_id.email or ""
 
-        return {
+        values = {
             'is_user': uid != public_id,
             'email': email,
-            'is_follower': is_follower
+            'is_follower': False,
         }
 
+        if not obj:
+            return values
+        obj_ids = obj.exists(cr, SUPERUSER_ID, [id], context=context)
+        if obj_ids:
+            if partner_id:
+                values['is_follower'] = len(
+                    request.registry['mail.followers'].search(
+                        cr, SUPERUSER_ID, [
+                            ('res_model', '=', 'mail.group'),
+                            ('res_id', '=', obj_ids[0]),
+                            ('partner_id', '=', partner_id.id)
+                        ], context=context)) == 1
+            if post.get('fields'):
+                record = obj.read(cr, SUPERUSER_ID, obj_ids[0], fields=post.get('fields'), context=context)
+                values.update(record)
+
+        return values
diff --git a/addons/website_mail/models/mail_message.py b/addons/website_mail/models/mail_message.py
index 1e50611fa009cf2f2ce9e9a3f416cf4c641b344a..cff950f2962e7aabd4fa85d2bb7da1f1601a6244 100644
--- a/addons/website_mail/models/mail_message.py
+++ b/addons/website_mail/models/mail_message.py
@@ -34,7 +34,7 @@ class MailMessage(osv.Model):
                 res[message.id] = message.subject
             else:
                 plaintext_ct = html2plaintext(message.body)
-                res[message.id] = plaintext_ct + '%s' % (' [...]' if len(plaintext_ct) >= 20 else '')
+                res[message.id] = plaintext_ct[:30] + '%s' % (' [...]' if len(plaintext_ct) >= 30 else '')
         return res
 
     _columns = {
diff --git a/addons/website_mail/static/src/js/website_mail.js b/addons/website_mail/static/src/js/website_mail.js
index bd34b526ddd020cd9896818632a21403c07b2c25..d069f88ea453759e35cd0e50f383115264438116 100644
--- a/addons/website_mail/static/src/js/website_mail.js
+++ b/addons/website_mail/static/src/js/website_mail.js
@@ -7,17 +7,20 @@
         selector: ".js_follow",
         start: function (editable_mode) {
             var self = this;
+            this.is_user = false;
 
-            // set value and display button
-            self.$target.find("input").removeClass("hidden");
             openerp.jsonRpc('/website_mail/is_follower', 'call', {
                 model: this.$target.data('object'),
-                id: +this.$target.data('id'),
+                id: this.$target.data('id'),
+                fields: ['name', 'alias_id'],
             }).always(function (data) {
+                self.is_user = data.is_user;
+                self.$target.find('.js_mg_email').attr('href', 'mailto:' + data.alias_id[1]);
+                self.$target.find('.js_mg_link').attr('href', '/groups/' + data.id);
+                self.toggle_subscription(data.is_follower);
                 self.$target.find('input.js_follow_email')
                     .val(data.email ? data.email : "")
-                    .attr("disabled", data.is_follower && data.email.length ? "disabled" : false);
-                self.$target.attr("data-follow", data.is_follower ? 'on' : 'off');
+                    .attr("disabled", data.is_follower || (data.email.length && self.is_user) ? "disabled" : false);
                 self.$target.removeClass("hidden");
             });
 
@@ -30,10 +33,11 @@
                     self.on_click();
                 });
             }
+            return;
         },
         on_click: function () {
             var self = this;
-            var $email = this.$target.find(".js_follow_email:visible");
+            var $email = this.$target.find(".js_follow_email");
 
             if ($email.length && !$email.val().match(/.+@.+/)) {
                 this.$target.addClass('has-error');
@@ -47,13 +51,27 @@
                 'message_is_follower': this.$target.attr("data-follow") || "off",
                 'email': $email.length ? $email.val() : false,
             }).then(function (follow) {
-                if (follow) {
-                    self.$target.find(".js_follow_email, .input-group-btn").addClass("hidden");
-                    self.$target.find(".alert").removeClass("hidden");
-                }
-                self.$target.find('input.js_follow_email').attr("disabled", follow ? "disabled" : false);
-                self.$target.attr("data-follow", follow ? 'on' : 'off');
+                self.toggle_subscription(follow);
             });
         },
+        toggle_subscription: function(follow) {
+            if (follow) {
+                this.$target.find(".js_mg_follow_form").addClass("hidden");
+                this.$target.find(".js_mg_details").removeClass("hidden");
+            }
+            else {
+                this.$target.find(".js_mg_follow_form").removeClass("hidden");
+                this.$target.find(".js_mg_details").addClass("hidden");
+            }
+            this.$target.find('input.js_follow_email').attr("disabled", follow || this.is_user ? "disabled" : false);
+            this.$target.attr("data-follow", follow ? 'on' : 'off');
+        },
+    });
+
+    $(document).ready(function () {
+        $('.js_follow_btn').on('click', function (ev) {
+            var email = $(ev.currentTarget).parents('.js_mg_follow_form').first().find('.js_follow_email').val();
+            $(document).find('.js_follow_email').val(email);
+        });
     });
 })();
diff --git a/addons/website_mail/views/snippets.xml b/addons/website_mail/views/snippets.xml
index 98a793932114088dea775dae5938f170536c8c92..987ccaa672e6ae082ce7d38caccec84336a6e34d 100644
--- a/addons/website_mail/views/snippets.xml
+++ b/addons/website_mail/views/snippets.xml
@@ -503,20 +503,25 @@
                 <span class="oe_snippet_thumbnail_title">Subscribe Button</span>
             </div>
 
-            <div class="oe_snippet_body input-group js_follow"
+            <div class="oe_snippet_body js_follow"
                       data-id="0"
                       data-object="mail.group"
                       data-follow="off">
-                <input
-                      type="email"
-                      name="email"
-                      class="js_follow_email form-control"
-                      placeholder="your email..."/>
-                <span class="input-group-btn">
-                    <a href="#" class="btn btn-default js_unfollow_btn">Unsubscribe</a>
-                    <a href="#" class="btn btn-primary js_follow_btn">Subscribe</a>
-                </span>
-                <div class="alert alert-success hidden">thanks for your subscription!</div>
+                <div class="input-group js_mg_follow_form">
+                    <input
+                          type="email"
+                          name="email"
+                          class="js_follow_email form-control"
+                          placeholder="your email..."/>
+                    <span class="input-group-btn">
+                        <button href="#" class="btn btn-primary js_follow_btn">Subscribe</button>
+                    </span>
+                </div>
+                <p class="js_mg_details hidden well well-sm">
+                    <i class="fa fa-envelope-o"/><a href="#" class="js_mg_email"> send mail</a> -
+                    <i class="fa fa-file-o"/><a href="#" class="js_mg_link"> archives</a> -
+                    <i class="fa fa-times"/><a href="#" class="js_unfollow_btn"> unsubscribe</a>
+                </p>
             </div>
 
         </div>
diff --git a/addons/website_mail_group/controllers/main.py b/addons/website_mail_group/controllers/main.py
index 88eb1a7e9b73fda434b36c3554d036c514643ab2..7320ebc6548a2b4e2c64ae68f68054c38453f95f 100644
--- a/addons/website_mail_group/controllers/main.py
+++ b/addons/website_mail_group/controllers/main.py
@@ -9,13 +9,14 @@ from openerp.addons.web.http import request
 
 
 class MailGroup(http.Controller):
-    _thread_per_page = 10
+    _thread_per_page = 20
+    _replies_per_page = 10
 
     def _get_archives(self, group_id):
         MailMessage = request.registry['mail.message']
         groups = MailMessage.read_group(
             request.cr, request.uid, [('model', '=', 'mail.group'), ('res_id', '=', group_id)], ['subject', 'date'],
-            groupby="date", orderby="date asc", context=request.context)
+            groupby="date", orderby="date desc", context=request.context)
         for group in groups:
             begin_date = datetime.datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
             end_date = datetime.datetime.strptime(group['__domain'][1][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
@@ -27,7 +28,7 @@ class MailGroup(http.Controller):
     def view(self, **post):
         cr, uid, context = request.cr, request.uid, request.context
         group_obj = request.registry.get('mail.group')
-        group_ids = group_obj.search(cr, uid, [], context=context)
+        group_ids = group_obj.search(cr, uid, [('alias_id', '!=', False), ('alias_id.alias_name', '!=', False)], context=context)
         values = {'groups': group_obj.browse(cr, uid, group_ids, context)}
         return request.website.render('website_mail_group.mail_groups', values)
 
@@ -73,6 +74,7 @@ class MailGroup(http.Controller):
             'archives': self._get_archives(group.id),
             'date_begin': date_begin,
             'date_end': date_end,
+            'replies_per_page': self._replies_per_page,
         }
         return request.website.render('website_mail_group.group_messages', values)
 
@@ -81,11 +83,49 @@ class MailGroup(http.Controller):
     ], type='http', auth="public", website=True)
     def thread_discussion(self, group, message, mode='thread', date_begin=None, date_end=None, **post):
         cr, uid, context = request.cr, request.uid, request.context
+        Message = request.registry['mail.message']
+        if mode == 'thread':
+            base_domain = [('model', '=', 'mail.group'), ('res_id', '=', group.id), ('parent_id', '=', message.parent_id and message.parent_id.id or False)]
+        else:
+            base_domain = [('model', '=', 'mail.group'), ('res_id', '=', group.id)]
+        next_message = None
+        next_message_ids = Message.search(cr, uid, base_domain + [('date', '<', message.date)], order="date DESC", limit=1, context=context)
+        if next_message_ids:
+            next_message = Message.browse(cr, uid, next_message_ids[0], context=context)
+        prev_message = None
+        prev_message_ids = Message.search(cr, uid, base_domain + [('date', '>', message.date)], order="date ASC", limit=1, context=context)
+        if prev_message_ids:
+            prev_message = Message.browse(cr, uid, prev_message_ids[0], context=context)
         values = {
             'message': message,
             'group': group,
             'mode': mode,
+            'archives': self._get_archives(group.id),
             'date_begin': date_begin,
             'date_end': date_end,
+            'replies_per_page': self._replies_per_page,
+            'next_message': next_message,
+            'prev_message': prev_message,
         }
         return request.website.render('website_mail_group.group_message', values)
+
+    @http.route(
+        '''/groups/<model('mail.group'):group>/<model('mail.message', "[('model','=','mail.group'), ('res_id','=',group[0])]"):message>/get_replies''',
+        type='json', auth="public", methods=['POST'], website=True)
+    def render_messages(self, group, message, **post):
+        last_displayed_id = post.get('last_displayed_id')
+        if not last_displayed_id:
+            return False
+        Message = request.registry['mail.message']
+        replies_domain = [('id', '<', int(last_displayed_id)), ('parent_id', '=', message.id)]
+        msg_ids = Message.search(request.cr, request.uid, replies_domain, limit=self._replies_per_page, context=request.context)
+        msg_count = Message.search(request.cr, request.uid, replies_domain, count=True, context=request.context)
+        messages = Message.browse(request.cr, request.uid, msg_ids, context=request.context)
+        values = {
+            'group': group,
+            'thread_header': message,
+            'messages': messages,
+            'msg_more_count': msg_count - self._replies_per_page,
+            'replies_per_page': self._replies_per_page,
+        }
+        return request.registry['ir.ui.view'].render(request.cr, request.uid, 'website_mail_group.messages_short', values, engine='ir.qweb', context=request.context)
diff --git a/addons/website_mail_group/static/src/css/website_mail_group.css b/addons/website_mail_group/static/src/css/website_mail_group.css
new file mode 100644
index 0000000000000000000000000000000000000000..27482ebd203e1e14f20604ed86a432ce4e3247c0
--- /dev/null
+++ b/addons/website_mail_group/static/src/css/website_mail_group.css
@@ -0,0 +1,12 @@
+.o_mg_avatar {
+    width: 40px;
+    height: 40px;
+}
+
+.o_mg_link_show {
+    display: none;
+}
+
+.o_mg_link_content {
+    display: none;
+}
diff --git a/addons/website_mail_group/static/src/js/website_mail_group.js b/addons/website_mail_group/static/src/js/website_mail_group.js
new file mode 100644
index 0000000000000000000000000000000000000000..c9b8ae797ed2fa85fd05ce473ad2b4cec5fe932e
--- /dev/null
+++ b/addons/website_mail_group/static/src/js/website_mail_group.js
@@ -0,0 +1,42 @@
+$(document).ready(function () {
+
+    $('.o_mg_link_hide').on('click', function (ev) {
+        ev.preventDefault();
+        var $link = $(ev.currentTarget);
+        var $container = $link.parents('div').first();
+        $container.find('.o_mg_link_hide').first().hide();
+        $container.find('.o_mg_link_show').first().show();
+        $container.find('.o_mg_link_content').first().show();
+        return false;
+    });
+
+    $('.o_mg_link_show').on('click', function (ev) {
+        ev.preventDefault();
+        var $link = $(ev.currentTarget);
+        var $container = $link.parents('div').first();
+        $container.find('.o_mg_link_hide').first().show();
+        $container.find('.o_mg_link_show').first().hide();
+        $container.find('.o_mg_link_content').first().hide();
+        return false;
+    });
+
+    $('body').on('click', 'button.o_mg_read_more', function (ev) {
+        var $link = $(ev.target);
+        return openerp.jsonRpc($link.data('href'), 'call', {
+            'last_displayed_id': $link.data('msg-id'),
+        }).then(function (data) {
+            if (! data) {
+                return true;
+            }
+            var $thread_container = $link.parents('.o_mg_replies').first().find('ul.media-list');
+            if ($thread_container) {
+                var $last_msg = $thread_container.find('li.media').last();
+                $(data).find('li.media').insertAfter($last_msg);
+                $(data).find('p.well').appendTo($thread_container);
+            }
+            var $show_more = $link.parents('p.well').first();
+            $show_more.remove();
+            return true;
+        });
+    });
+});
\ No newline at end of file
diff --git a/addons/website_mail_group/views/website_mail_group.xml b/addons/website_mail_group/views/website_mail_group.xml
index 87f8755c04a8e20700ca94d497e723955a9f18f2..76edd5247536de81f18499a9932689dd495ec20d 100644
--- a/addons/website_mail_group/views/website_mail_group.xml
+++ b/addons/website_mail_group/views/website_mail_group.xml
@@ -1,152 +1,240 @@
 <?xml version="1.0" encoding="utf-8"?>
 <openerp>
 <data>
-    <template id="footer_mailing_list" inherit_id="website.layout" name="Footer Mailing List Link">
-        <xpath expr="//footer//div[@name='info']/ul" position="inside">
-            <li><a t-attf-href="/groups">Mailing List</a></li>
-        </xpath>
-    </template>
-    <template id="mail_groups" name="Mailing Lists">
-        <t t-call="website.layout">
-            <div class="container">
-                <h1>
-                    Our Mailing Lists
-                </h1>
-                <div class="row">
-                    <div class="col-sm-4" style="height: 140px" t-foreach="groups" t-as="group">
-                        <img t-att-src="'/website/image?model=mail.group&amp;field=image_small&amp;id='+str(group['id'])" class="pull-left"/>
-                        <div>
-                            <strong><a t-attf-href="/groups/#{ slug(group) }" t-esc="group.name"/></strong>
-                            <div t-esc="group.description" class="text-muted"/>
-                            <t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
-                        </div>
-                    </div>
+
+<template id="footer_mailing_list" inherit_id="website.layout" name="Footer Mailing List Link">
+    <xpath expr="//footer//div[@name='info']/ul" position="inside">
+        <li><a t-attf-href="/groups">Mailing List</a></li>
+    </xpath>
+</template>
+
+<template id="mail_groups" name="Mailing Lists">
+    <t t-call="website.layout">
+        <div id="wrap" class="oe_structure oe_empty">
+            <section class="bg-primary jumbotron mt0 mb0">
+                <div class="container">
+                    <h1>Stay in touch with our Community</h1>
+                    <p>Alone we can do so little, together we can do so much</p>
+                </div>
+            </section>
+        </div>
+        <div class="container mt32">
+            <div class="row mt8" t-foreach="groups" t-as="group">
+                <div class="col-md-3">
+                    <img t-att-src="'/website/image?model=mail.group&amp;field=image_small&amp;id='+str(group['id'])" class="pull-left"/>
+                    <strong><a t-attf-href="/groups/#{ slug(group) }" t-esc="group.name"/></strong><br />
+                    <i class='fa fa-envelope-o'/>
+                    <a t-attf-href="mailto:#{group.alias_id.alias_name}@#{group.alias_id.alias_domain}"><span t-field="group.alias_id"/></a>
+                </div>
+                <div class="col-md-4">
+                    <div t-esc="group.description" class="text-muted"/>
+                </div>
+                <div class="col-md-2">
+                    <i class='fa fa-user'/> <t t-esc="len(group.message_follower_ids)"/> participants<br />
+                    <i class='fa fa-envelope-o'/> <t t-esc="len(group.message_ids)"/> messages
+                </div>
+                <div class="col-md-3">
+                    <t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
                 </div>
             </div>
-        </t>
-    </template>
+        </div>
+    </t>
+</template>
 
-    <template id="group_messages" name="Message Threads">
-        <t t-call="website.layout">
-            <section class="container">
-                <div class="row mt8">
-                    <div class="col-md-5 mt16">
-                        <ol class="breadcrumb">
-                            <li><a href="/groups">Mailing Lists</a></li>
-                            <li class="active" t-esc="group.name"/>
-                        </ol>
-                    </div>
-                    <div class="col-md-5 pull-right">
-                        <t t-call="website.pager"/>
-                    </div>
+<template id="group_messages" name="Message Threads">
+    <t t-call="website.layout">
+        <t t-set="head">
+            <link rel='stylesheet' href="/website_mail_group/static/src/css/website_mail_group.css"/>
+            <script type="text/javascript" src="/website_mail_group/static/src/js/website_mail_group.js"/>
+        </t>
+        <section class="container">
+            <div class="row mt8">
+                <ol class="breadcrumb pull-left">
+                    <li><a href="/groups">Mailing Lists</a></li>
+                    <li>
+                        <a t-attf-href="/groups/#{slug(group)}?#{mode and 'mode=%s' % mode or ''}#{date_begin and '&amp;date_begin=%s' % date_begin or ''}#{date_end and '&amp;date_end=%s' % date_end or ''}"><t t-esc="group.name"/></a>
+                    </li>
+                </ol>
+            </div>
+            <div class="row">
+                <h1 class="text-center">
+                    <t t-esc="group.name"/> mailing list archives
+                </h1><h4 class="text-center text-muted">
+                    <i class='fa fa-envelope-o'/>
+                    <a t-attf-href="mailto:#{group.alias_id.alias_name}@#{group.alias_id.alias_domain}"><span t-field="group.alias_id"/></a>
+                </h4>
+            </div>
+            <div class="row">
+                <div class="col-md-3">
+                    <h2>Archives</h2>
+                    <ul class="nav nav-pills nav-stacked" id="group_mode">
+                        <li t-attf-class="#{mode=='thread' and 'active' or ''}">
+                            <a t-attf-href="/groups/#{ slug(group) }?mode=thread">By thread</a>
+                        </li>
+                        <li t-attf-class="#{mode=='date' and not date_begin and 'active' or ''}">
+                            <a t-attf-href="/groups/#{ slug(group) }?mode=date">By date</a>
+                            <ul class="nav nav-pills nav-stacked" style="margin-left: 8px;">
+                                <t t-foreach="archives" t-as="month_archive">
+                                <li t-att-class="month_archive['date_begin'] == date_begin and 'active' or None">
+                                    <a t-ignore="True" t-attf-href="/groups/#{ slug(group) }?mode=date&amp;date_begin=#{ month_archive['date_begin'] }&amp;date_end=#{month_archive['date_end']}">
+                                        <t t-esc="month_archive['date']"/>
+                                        <span class="pull-right badge" t-esc="month_archive['date_count']"/>
+                                    </a>
+                                </li>
+                                </t>
+                            </ul>
+                        </li>
+                    </ul>
                 </div>
-                <h1 class="mt8 mb32">
-                    <span t-field="group.name"/>
-                    <small>List Archive</small>
-                </h1>
-                <div class="row">
-                    <div class="col-md-3">
-                        <ul class="nav nav-pills nav-stacked" id="group_mode">
-                            <li t-attf-class="#{mode=='thread' and 'active' or ''}">
-                                <a t-attf-href="/groups/#{ slug(group) }?mode=thread">By thread</a>
-                            </li>
-                            <li t-attf-class="#{mode=='date' and not date_begin and 'active' or ''}">
-                                <a t-attf-href="/groups/#{ slug(group) }?mode=date">By date</a>
-                                <ul class="nav nav-pills nav-stacked" style="margin-left: 8px;">
-                                    <t t-foreach="archives" t-as="month_archive">
-                                    <li t-att-class="month_archive['date_begin'] == date_begin and 'active' or None">
-                                        <a t-ignore="True" t-attf-href="/groups/#{ slug(group) }?mode=date&amp;date_begin=#{ month_archive['date_begin'] }&amp;date_end=#{month_archive['date_end']}">
-                                            <t t-esc="month_archive['date']"/>
-                                            <span class="pull-right badge" t-esc="month_archive['date_count']"/>
-                                        </a>
-                                    </li>
-                                    </t>
-                                </ul>
-                            </li>
-                        </ul>
-                    </div>
-                    <div class="col-md-9">
-                        <t t-call="website_mail_group.messages_short"/>
+                <div class="col-md-9">
+                    <div>
+                        <t t-call="website.pager"/>
                     </div>
-                </div>
-            </section>
-        </t>
-    </template>
-
-    <template id="group_message">
-        <t t-call="website.layout">
-            <div class="container">
-                <div class="row mt8">
-                    <div class="col-md-5">
-                        <ol class="breadcrumb mb8">
-                            <li><a href="/groups">Mailing Lists</a></li>
-                            <li>
-                                <a t-attf-href="/groups/#{slug(group)}?mode=#{mode}&amp;date_begin=#{date_begin}&amp;date_end=#{date_end}">
-                                    <span t-field="group.name"/>
-                                </a>
-                            </li>
-                            <li class="active" t-esc="message.subject or 'Message'"/>
-                        </ol>
+                    <t t-call="website_mail_group.messages_short">
+                        <t t-set="messages" t-value="messages"/>
+                        <t t-set="msg_more_count" t-value="0"/>
+                        <t t-set="thread_header" t-value="None"/>
+                    </t>
+                    <div>
+                        <t t-call="website.pager"/>
                     </div>
                 </div>
+            </div>
+        </section>
+    </t>
+</template>
 
-                <h1 t-field="message.subject"/>
-                <img class="img-rounded pull-left" t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(message.id)" style="width : 30px"/>
-                <h4 class="mt0 mb32">
-                    <t t-if="message.author_id">
-                         <span t-field="message.author_id" style="display: inline-block;" t-field-options='{
-                                "widget": "contact",
-                                "fields": ["name"]
-                            }'/>
-                    </t>
-                    <t t-if="not message.author_id"><t t-esc="message.email_from"/></t>
-                    on <span t-field="message.date"/>
+<template id="group_message">
+    <t t-call="website.layout">
+        <t t-set="head">
+            <link rel='stylesheet' href="/website_mail_group/static/src/css/website_mail_group.css"/>
+            <script type="text/javascript" src="/website_mail_group/static/src/js/website_mail_group.js"/>
+        </t>
+        <section class="container">
+            <div class="row mt8">
+                <ol class="breadcrumb pull-left">
+                    <li><a href="/groups">Mailing Lists</a></li>
+                    <li>
+                        <a t-attf-href="/groups/#{slug(group)}?#{mode and 'mode=%s' % mode or ''}#{date_begin and '&amp;date_begin=%s' % date_begin or ''}#{date_end and '&amp;date_end=%s' % date_end or ''}"><t t-esc="group.name"/></a>
+                    </li>
+                    <li t-if="message" class="active"><t t-esc="message.description"/></li>
+                </ol>
+            </div>
+            <div class="row">
+                <h1 class="text-center">
+                    <t t-esc="group.name"/> mailing list archives
+                </h1><h4 class="text-center text-muted">
+                    <i class='fa fa-envelope-o'/>
+                    <a t-attf-href="mailto:#{group.alias_id.alias_name}@#{group.alias_id.alias_domain}"><span t-field="group.alias_id"/></a>
                 </h4>
-                <div t-raw="message.body"/>
-
-                <div class="row" t-if="message.attachment_ids">
-                    <h3 class="col-sm-12">Attachment(s):</h3>
-                    <div class="col-md-2 col-sm-3 text-center" t-foreach='message.attachment_ids' t-as='attachment'>
-                        <a t-att-href="'/mail/download_attachment?model=mail.message&amp;id='+str(message.id)+'&amp;method=download_attachment&amp;attachment_id='+str(attachment.id)" target="_blank">
-                            <t t-if="attachment.file_type == 'webimage'">
-                                <img t-att-src="'/web/binary/image?model=ir.attachment&amp;field=datas&amp;id=' + str(attachment.id) + '&amp;resize=100,80'"
-                                    class='oe_attachment_embedded'></img>
-                            </t>
-                            <t t-if="attachment.file_type != 'webimage'">
-                                <img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.file_type + '.png'"
-                                    class='oe_attachment_webimage'></img>
-                            </t>
-                            <div class='oe_attachment_name'><t t-raw='attachment.name' /></div>
-                        </a>
-                    </div>
-                </div>
-                <div t-if="message.child_ids">
-                    <h2 class="page-header">Follow ups</h2>
-                    <t t-set="messages" t-value="message.child_ids"/>
-                    <t t-call="website_mail_group.messages_short"/>
-                </div>
-                <div t-if="message.parent_id">
-                    <h2 class="page-header">Reference</h2>
-                    <t t-set="messages" t-value="[message.parent_id]"/>
-                    <t t-call="website_mail_group.messages_short"/>
+            </div>
+            <div class="row">
+                <div class="col-md-3">
+                    <h4>Browse archives</h4>
+                    <ul class="nav nav-pills nav-stacked" id="group_mode">
+                        <li t-attf-class="#{mode=='thread' and 'active' or ''}">
+                            <a t-attf-href="/groups/#{ slug(group) }?mode=thread">By thread</a>
+                        </li>
+                        <li t-attf-class="#{mode=='date' and not date_begin and 'active' or ''}">
+                            <a t-attf-href="/groups/#{ slug(group) }?mode=date">By date</a>
+                            <ul class="nav nav-pills nav-stacked" style="margin-left: 8px;">
+                                <t t-foreach="archives" t-as="month_archive">
+                                <li t-att-class="month_archive['date_begin'] == date_begin and 'active' or None">
+                                    <a t-ignore="True" t-attf-href="/groups/#{ slug(group) }?mode=date&amp;date_begin=#{ month_archive['date_begin'] }&amp;date_end=#{month_archive['date_end']}">
+                                        <t t-esc="month_archive['date']"/>
+                                        <span class="pull-right badge" t-esc="month_archive['date_count']"/>
+                                    </a>
+                                </li>
+                                </t>
+                            </ul>
+                        </li>
+                    </ul>
                 </div>
+                <div class="col-md-9">
+                    <div class="row">
+                        <h4 class="col-md-6">
+                            <t t-if="prev_message"><a t-attf-href='/groups/#{slug(group)}/#{slug(prev_message)}?#{mode and "mode=%s" % mode or ""}'>
+                                <i class="fa fa-arrow-left"/> <t t-esc="prev_message.description"/>
+                            </a></t>
+                        </h4>
+                        <h4 class="col-md-6">
+                            <t t-if="next_message"><a class="pull-right" t-attf-href='/groups/#{slug(group)}/#{slug(next_message)}?#{mode and "mode=%s" % mode or ""}'>
+                                <t t-esc="next_message.description"/> <i class="fa fa-arrow-right"/>
+                            </a></t>
+                        </h4>
+                    </div>
+                    <div class="media">
+                        <img class="img-rounded pull-left mt0 media-object o_mg_avatar"
+                            t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(message.id)"/>
+                        <div class="media-body">
+                            <h4 class="media-heading" t-esc="message.description"/>
+                            <small>
+                                by
+                                <t t-if="message.author_id">
+                                    <span t-field="message.author_id" style="display: inline-block;" t-field-options='{
+                                        "widget": "contact",
+                                        "fields": ["name"]
+                                    }'/>
+                                </t>
+                                <t t-if="not message.author_id"><t t-esc="message.email_from"/></t>
+                                - <i class="fa fa-calendar"/> <t t-esc="message.date"/>
+                            </small>
+                            <div t-raw="message.body"/>
 
-                <div class="jumbotron mt64">
-                    <h1>Join the discussion</h1>
-                    <p>
-                        Join this mailing list to follow or participate to this discussion.<br/>
-                        <span t-field="group.name"/>: <i t-field="group.description"/>
-                    </p>
-                    <t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
+                            <div>
+                                <p t-if="message.attachment_ids" class="mt8">
+                                    <a href="#" class="o_mg_link_hide">
+                                        <i class="fa fa-chevron-right"/> <t t-raw="len(message.attachment_ids)"/> attachments
+                                    </a>
+                                    <a href="#" class="o_mg_link_show">
+                                        <i class="fa fa-chevron-down"/> <t t-raw="len(message.attachment_ids)"/> attachments
+                                    </a>
+                                </p>
+                                <div class="o_mg_link_content">
+                                    <div class="col-md-2 col-sm-3 text-center" t-foreach='message.attachment_ids' t-as='attachment'>
+                                        <a t-att-href="'/mail/download_attachment?model=mail.message&amp;id='+str(message.id)+'&amp;method=download_attachment&amp;attachment_id='+str(attachment.id)" target="_blank">
+                                            <t t-if="attachment.file_type == 'webimage'">
+                                                <img t-att-src="'/web/binary/image?model=ir.attachment&amp;field=datas&amp;id=' + str(attachment.id) + '&amp;resize=100,80'"
+                                                    class='oe_attachment_embedded'
+                                                    t-att-title="attachment.name"/>
+                                            </t>
+                                            <t t-if="attachment.file_type != 'webimage'">
+                                                <img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.file_type + '.png'"
+                                                    class='oe_attachment_webimage'
+                                                    t-att-title="attachment.name"/>
+                                            </t>
+                                            <div class='oe_attachment_name'><t t-raw='attachment.name' /></div>
+                                        </a>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div t-if="message.child_ids" class="o_mg_replies">
+                        <h4 class="page-header">Follow-Ups</h4>
+                        <t t-call="website_mail_group.messages_short">
+                            <t t-set="messages" t-value="message.child_ids[:replies_per_page]"/>
+                            <t t-set="msg_more_count" t-value="len(message.child_ids) - replies_per_page"/>
+                            <t t-set="thread_header" t-value="message"/>
+                        </t>
+                    </div>
+                    <div t-if="message.parent_id">
+                        <h4 class="page-header">Reference</h4>
+                        <t t-call="website_mail_group.messages_short">
+                            <t t-set="messages" t-value="[message.parent_id]"/>
+                        </t>
+                    </div>
                 </div>
             </div>
-        </t>
-    </template>
+        </section>
+    </t>
+</template>
 
-    <template id="messages_short">
+<template id="messages_short">
+    <div>
         <ul class="media-list">
             <li t-foreach="messages" t-as="thread" class="media">
-                <img class="img-rounded pull-left mt0 media-object" style="height: 40px"
+                <img class="img-rounded pull-left mt0 media-object o_mg_avatar"
                     t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(thread.id)"/>
                 <div class="media-body">
                     <h4 class="media-heading">
@@ -161,14 +249,36 @@
                             }'/>
                         </t>
                         <t t-if="not thread.author_id"><t t-esc="thread.email_from"/></t>
-                        <span class="fa fa-comment-o">
-                            <t t-raw="len(thread.child_ids)"/> replies
-                        </span>
+                        - <i class="fa fa-calendar"/> <t t-esc="thread.date"/>
+                        - <i class="fa fa-paperclip"/> <t t-esc="len(thread.attachment_ids)"/>
                     </small>
+                    <p t-if="thread.child_ids" class="mt8">
+                        <a href="#" class="o_mg_link_hide">
+                            <i class="fa fa-chevron-right"/> <t t-raw="len(thread.child_ids)"/> replies
+                        </a>
+                        <a href="#" class="o_mg_link_show">
+                            <i class="fa fa-chevron-down"/> <t t-raw="len(thread.child_ids)"/> replies
+                        </a>
+                    </p>
+                    <div class="o_mg_link_content o_mg_replies">
+                        <t t-call="website_mail_group.messages_short">
+                            <t t-set="messages" t-value="thread.child_ids[:replies_per_page]"/>
+                            <t t-set="msg_more_count" t-value="len(thread.child_ids) - replies_per_page"/>
+                            <t t-set="thread_header" t-value="thread"/>
+                        </t>
+                    </div>
                 </div>
             </li>
         </ul>
-    </template>
+        <p t-if="messages and msg_more_count > 0 and thread_header" class="well well-sm">
+            <button class="fa btn-link o_mg_read_more"
+                t-attf-data-href="/groups/#{slug(group)}/#{slug(thread_header)}/get_replies"
+                t-attf-data-msg-id="#{messages[-1].id}">
+                show <t t-esc="msg_more_count"/> more replies
+            </button>
+        </p>
+    </div>
+</template>
 
 </data>
 </openerp>
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index bbd8f83fd7d9afc577b7028bd4f712ff02cb4b00..6df34f232b4f6b211aa6d43bd1b157641999b2a8 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -35,8 +35,8 @@ class table_compute(object):
         index = 0
         maxy = 0
         for p in products:
-            x = p.website_size_x
-            y = p.website_size_y
+            x = min(max(p.website_size_x, 1), PPR)
+            y = min(max(p.website_size_y, 1), PPR)
             if index>PPG:
                 x = y = 1
 
diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py
index daa2a61c8518c19cf9e0918ccc6603d80f18bc43..0911887c8353e0ff067b935e41ded05f421bdee5 100644
--- a/addons/website_sale/models/product.py
+++ b/addons/website_sale/models/product.py
@@ -65,6 +65,7 @@ class product_template(osv.Model):
     _inherit = ["product.template", "website.seo.metadata"]
     _order = 'website_published desc, website_sequence desc, name'
     _name = 'product.template'
+    _mail_post_access = 'read'
 
     def _website_url(self, cr, uid, ids, field_name, arg, context=None):
         res = dict.fromkeys(ids, '')
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index 0c69ece50cc5a480ac8130bb89bf69339193cc85..8e96628c38bff5b70bf94b578ade03b23dcf3cf0 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -5,7 +5,7 @@
 <!-- Layout and common templates -->
 
 <template id="debugger" inherit_id="website.debugger" name="Event Debugger">
-    <xpath expr="//script[last()]" position="after">
+    <xpath expr='//t[@t-set="debugger_hook"]' position="after">
         <script type="text/javascript" src="/website_sale/static/src/js/website.tour.sale.js"></script>
     </xpath>
 </template>
diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py
index 57f24c8864adde2546eabc35e42b2201424d46b2..e9de9dc70288ca814fdea448955b89ade36a3525 100644
--- a/openerp/addons/base/ir/ir_actions.py
+++ b/openerp/addons/base/ir/ir_actions.py
@@ -41,6 +41,7 @@ import openerp.workflow
 
 _logger = logging.getLogger(__name__)
 
+
 class actions(osv.osv):
     _name = 'ir.actions.actions'
     _table = 'ir_actions'
@@ -129,9 +130,15 @@ class ir_actions_report_xml(osv.osv):
         Look up a report definition and render the report for the provided IDs.
         """
         new_report = self._lookup_report(cr, name)
-        # in order to use current yml test files with qweb reports
-        if isinstance(new_report, (str, unicode)):
-            return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf'
+
+        if isinstance(new_report, (str, unicode)):  # Qweb report
+            # The only case where a QWeb report is rendered with this method occurs when running
+            # yml tests originally written for RML reports.
+            if openerp.tools.config['test_enable'] and not tools.config['test_report_directory']:
+                # Only generate the pdf when a destination folder has been provided.
+                return self.pool['report'].get_html(cr, uid, res_ids, new_report, data=data, context=context), 'html'
+            else:
+                return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf'
         else:
             return new_report.create(cr, uid, res_ids, data, context)
 
@@ -1182,7 +1189,4 @@ class ir_actions_act_client(osv.osv):
 
     }
 
-
-
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/openerp/http.py b/openerp/http.py
index 0627c7695550a6c77dd72e3dc2cb8a0812fd483f..d0e4cf4d2eb8d95bb9e38f5245aa348eb8b43cfd 100644
--- a/openerp/http.py
+++ b/openerp/http.py
@@ -269,7 +269,10 @@ class WebRequest(object):
         """Called within an except block to allow converting exceptions
            to abitrary responses. Anything returned (except None) will
            be used as response.""" 
-        raise 
+        self._failed = exception # prevent tx commit
+        if isinstance(exception, werkzeug.exceptions.HTTPException):
+            return exception
+        raise
 
     def _call_function(self, *args, **kwargs):
         request = self
@@ -456,18 +459,20 @@ class JsonRequest(WebRequest):
     def _handle_exception(self, exception):
         """Called within an except block to allow converting exceptions
            to abitrary responses. Anything returned (except None) will
-           be used as response.""" 
-        _logger.exception("Exception during JSON request handling.")
-        self._failed = exception # prevent tx commit            
-        error = {
-                'code': 200,
-                'message': "OpenERP Server Error",
-                'data': serialize_exception(exception)
-        }
-        if isinstance(exception, AuthenticationError):
-            error['code'] = 100
-            error['message'] = "OpenERP Session Invalid"
-        return self._json_response(error=error)
+           be used as response."""
+        try:
+            return super(JsonRequest, self)._handle_exception(exception)
+        except Exception:
+            _logger.exception("Exception during JSON request handling.")
+            error = {
+                    'code': 200,
+                    'message': "OpenERP Server Error",
+                    'data': serialize_exception(exception)
+            }
+            if isinstance(exception, AuthenticationError):
+                error['code'] = 100
+                error['message'] = "OpenERP Session Invalid"
+            return self._json_response(error=error)
 
     def dispatch(self):
         """ Calls the method asked for by the JSON-RPC2 or JSONP request
diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py
index 6ce69578a8e16e006d084f0cf621be67e0f7d48b..af046836192be2f56201c5276813349987f0b317 100644
--- a/openerp/report/render/rml2pdf/trml2pdf.py
+++ b/openerp/report/render/rml2pdf/trml2pdf.py
@@ -107,7 +107,7 @@ class NumberedCanvas(canvas.Canvas):
         self.setFont("Helvetica", 8)
         self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40),
             " %(this)i / %(total)i" % {
-               'this': self._pageNumber+1,
+               'this': self._pageNumber,
                'total': page_count,
             }
         )
diff --git a/openerp/tools/test_reports.py b/openerp/tools/test_reports.py
index c008c20ae29887ece957f8dde79f77cb4957ec6f..305d2b0f115890c8f2195156cd7ea84b63b68df5 100644
--- a/openerp/tools/test_reports.py
+++ b/openerp/tools/test_reports.py
@@ -87,8 +87,7 @@ def try_report(cr, uid, rname, ids, data=None, context=None, our_module=None, re
                 if ('[[' in line) or ('[ [' in line):
                     _logger.error("Report %s may have bad expression near: \"%s\".", rname, line[80:])
             # TODO more checks, what else can be a sign of a faulty report?
-    elif res_format == 'foobar':
-        # TODO
+    elif res_format == 'html':
         pass
     else:
         _logger.warning("Report %s produced a \"%s\" chunk, cannot examine it", rname, res_format)